Coverage Report

Created: 2020-09-19 12:23

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Tooling/Syntax/Mutations.cpp
Line
Count
Source (jump to first uncovered line)
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
// This class has access to the internals of tree nodes. Its sole purpose is to
27
// define helpers that allow implementing the high-level mutation operations.
28
class syntax::MutationsImpl {
29
public:
30
  /// Add a new node with a specified role.
31
0
  static void addAfter(syntax::Node *Anchor, syntax::Node *New, NodeRole Role) {
32
0
    assert(Anchor != nullptr);
33
0
    assert(New->Parent == nullptr);
34
0
    assert(New->NextSibling == nullptr);
35
0
    assert(!New->isDetached());
36
0
    assert(Role != NodeRole::Detached);
37
0
38
0
    New->setRole(Role);
39
0
    auto *P = Anchor->getParent();
40
0
    P->replaceChildRangeLowLevel(Anchor, Anchor, New);
41
0
42
0
    P->assertInvariants();
43
0
  }
44
45
  /// Replace the node, keeping the role.
46
14
  static void replace(syntax::Node *Old, syntax::Node *New) {
47
14
    assert(Old != nullptr);
48
14
    assert(Old->Parent != nullptr);
49
14
    assert(Old->canModify());
50
14
    assert(New->Parent == nullptr);
51
14
    assert(New->NextSibling == nullptr);
52
14
    assert(New->isDetached());
53
14
54
14
    New->Role = Old->Role;
55
14
    auto *P = Old->getParent();
56
14
    P->replaceChildRangeLowLevel(findPrevious(Old), Old->getNextSibling(), New);
57
14
58
14
    P->assertInvariants();
59
14
  }
60
61
  /// Completely remove the node from its parent.
62
28
  static void remove(syntax::Node *N) {
63
28
    auto *P = N->getParent();
64
28
    P->replaceChildRangeLowLevel(findPrevious(N), N->getNextSibling(),
65
28
                                 /*New=*/nullptr);
66
28
67
28
    P->assertInvariants();
68
28
    N->assertInvariants();
69
28
  }
70
71
private:
72
42
  static syntax::Node *findPrevious(syntax::Node *N) {
73
42
    if (N->getParent()->getFirstChild() == N)
74
0
      return nullptr;
75
84
    
for (syntax::Node *C = N->getParent()->getFirstChild(); 42
C != nullptr;
76
84
         
C = C->getNextSibling()42
) {
77
84
      if (C->getNextSibling() == N)
78
42
        return C;
79
84
    }
80
42
    
llvm_unreachable0
("could not find a child node");
81
42
  }
82
};
83
84
42
void syntax::removeStatement(syntax::Arena &A, syntax::Statement *S) {
85
42
  assert(S);
86
42
  assert(S->canModify());
87
42
88
42
  if (isa<CompoundStatement>(S->getParent())) {
89
    // A child of CompoundStatement can just be safely removed.
90
28
    MutationsImpl::remove(S);
91
28
    return;
92
28
  }
93
  // For the rest, we have to replace with an empty statement.
94
14
  if (isa<EmptyStatement>(S))
95
0
    return; // already an empty statement, nothing to do.
96
14
97
14
  MutationsImpl::replace(S, createEmptyStatement(A));
98
14
}