Coverage Report

Created: 2020-09-19 12:23

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Tooling/Transformer/Stencil.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- Stencil.cpp - Stencil implementation -------------------*- 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
9
#include "clang/Tooling/Transformer/Stencil.h"
10
#include "clang/AST/ASTContext.h"
11
#include "clang/AST/ASTTypeTraits.h"
12
#include "clang/AST/Expr.h"
13
#include "clang/ASTMatchers/ASTMatchFinder.h"
14
#include "clang/ASTMatchers/ASTMatchers.h"
15
#include "clang/Basic/SourceLocation.h"
16
#include "clang/Lex/Lexer.h"
17
#include "clang/Tooling/Transformer/SourceCode.h"
18
#include "clang/Tooling/Transformer/SourceCodeBuilders.h"
19
#include "llvm/ADT/SmallVector.h"
20
#include "llvm/ADT/Twine.h"
21
#include "llvm/Support/Errc.h"
22
#include "llvm/Support/Error.h"
23
#include <atomic>
24
#include <memory>
25
#include <string>
26
27
using namespace clang;
28
using namespace transformer;
29
30
using ast_matchers::MatchFinder;
31
using llvm::errc;
32
using llvm::Error;
33
using llvm::Expected;
34
using llvm::StringError;
35
36
static llvm::Expected<DynTypedNode>
37
0
getNode(const ast_matchers::BoundNodes &Nodes, StringRef Id) {
38
0
  auto &NodesMap = Nodes.getMap();
39
0
  auto It = NodesMap.find(Id);
40
0
  if (It == NodesMap.end())
41
0
    return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
42
0
                                               "Id not bound: " + Id);
43
0
  return It->second;
44
0
}
45
46
namespace {
47
// An arbitrary fragment of code within a stencil.
48
struct RawTextData {
49
114
  explicit RawTextData(std::string T) : Text(std::move(T)) {}
50
  std::string Text;
51
};
52
53
// A debugging operation to dump the AST for a particular (bound) AST node.
54
struct DebugPrintNodeData {
55
1
  explicit DebugPrintNodeData(std::string S) : Id(std::move(S)) {}
56
  std::string Id;
57
};
58
59
// Operators that take a single node Id as an argument.
60
enum class UnaryNodeOperator {
61
  Parens,
62
  Deref,
63
  MaybeDeref,
64
  AddressOf,
65
  MaybeAddressOf,
66
};
67
68
// Generic container for stencil operations with a (single) node-id argument.
69
struct UnaryOperationData {
70
  UnaryOperationData(UnaryNodeOperator Op, std::string Id)
71
20
      : Op(Op), Id(std::move(Id)) {}
72
  UnaryNodeOperator Op;
73
  std::string Id;
74
};
75
76
// The fragment of code corresponding to the selected range.
77
struct SelectorData {
78
12
  explicit SelectorData(RangeSelector S) : Selector(std::move(S)) {}
79
  RangeSelector Selector;
80
};
81
82
// A stencil operation to build a member access `e.m` or `e->m`, as appropriate.
83
struct AccessData {
84
  AccessData(StringRef BaseId, Stencil Member)
85
15
      : BaseId(std::string(BaseId)), Member(std::move(Member)) {}
86
  std::string BaseId;
87
  Stencil Member;
88
};
89
90
struct IfBoundData {
91
  IfBoundData(StringRef Id, Stencil TrueStencil, Stencil FalseStencil)
92
      : Id(std::string(Id)), TrueStencil(std::move(TrueStencil)),
93
5
        FalseStencil(std::move(FalseStencil)) {}
94
  std::string Id;
95
  Stencil TrueStencil;
96
  Stencil FalseStencil;
97
};
98
99
struct SequenceData {
100
6
  SequenceData(std::vector<Stencil> Stencils) : Stencils(std::move(Stencils)) {}
101
  std::vector<Stencil> Stencils;
102
};
103
104
18
std::string toStringData(const RawTextData &Data) {
105
18
  std::string Result;
106
18
  llvm::raw_string_ostream OS(Result);
107
18
  OS << "\"";
108
18
  OS.write_escaped(Data.Text);
109
18
  OS << "\"";
110
18
  OS.flush();
111
18
  return Result;
112
18
}
113
114
1
std::string toStringData(const DebugPrintNodeData &Data) {
115
1
  return (llvm::Twine("dPrint(\"") + Data.Id + "\")").str();
116
1
}
117
118
3
std::string toStringData(const UnaryOperationData &Data) {
119
3
  StringRef OpName;
120
3
  switch (Data.Op) {
121
1
  case UnaryNodeOperator::Parens:
122
1
    OpName = "expression";
123
1
    break;
124
1
  case UnaryNodeOperator::Deref:
125
1
    OpName = "deref";
126
1
    break;
127
0
  case UnaryNodeOperator::MaybeDeref:
128
0
    OpName = "maybeDeref";
129
0
    break;
130
1
  case UnaryNodeOperator::AddressOf:
131
1
    OpName = "addressOf";
132
1
    break;
133
0
  case UnaryNodeOperator::MaybeAddressOf:
134
0
    OpName = "maybeAddressOf";
135
0
    break;
136
3
  }
137
3
  return (OpName + "(\"" + Data.Id + "\")").str();
138
3
}
139
140
2
std::string toStringData(const SelectorData &) { return "selection(...)"; }
141
142
8
std::string toStringData(const AccessData &Data) {
143
8
  return (llvm::Twine("access(\"") + Data.BaseId + "\", " +
144
8
          Data.Member->toString() + ")")
145
8
      .str();
146
8
}
147
148
3
std::string toStringData(const IfBoundData &Data) {
149
3
  return (llvm::Twine("ifBound(\"") + Data.Id + "\", " +
150
3
          Data.TrueStencil->toString() + ", " + Data.FalseStencil->toString() +
151
3
          ")")
152
3
      .str();
153
3
}
154
155
1
std::string toStringData(const MatchConsumer<std::string> &) {
156
1
  return "run(...)";
157
1
}
158
159
4
std::string toStringData(const SequenceData &Data) {
160
4
  llvm::SmallVector<std::string, 2> Parts;
161
4
  Parts.reserve(Data.Stencils.size());
162
4
  for (const auto &S : Data.Stencils)
163
10
    Parts.push_back(S->toString());
164
4
  return (llvm::Twine("seq(") + llvm::join(Parts, ", ") + ")").str();
165
4
}
166
167
// The `evalData()` overloads evaluate the given stencil data to a string, given
168
// the match result, and append it to `Result`. We define an overload for each
169
// type of stencil data.
170
171
Error evalData(const RawTextData &Data, const MatchFinder::MatchResult &,
172
102
               std::string *Result) {
173
102
  Result->append(Data.Text);
174
102
  return Error::success();
175
102
}
176
177
Error evalData(const DebugPrintNodeData &Data,
178
0
               const MatchFinder::MatchResult &Match, std::string *Result) {
179
0
  std::string Output;
180
0
  llvm::raw_string_ostream Os(Output);
181
0
  auto NodeOrErr = getNode(Match.Nodes, Data.Id);
182
0
  if (auto Err = NodeOrErr.takeError())
183
0
    return Err;
184
0
  NodeOrErr->print(Os, PrintingPolicy(Match.Context->getLangOpts()));
185
0
  *Result += Os.str();
186
0
  return Error::success();
187
0
}
188
189
Error evalData(const UnaryOperationData &Data,
190
17
               const MatchFinder::MatchResult &Match, std::string *Result) {
191
17
  const auto *E = Match.Nodes.getNodeAs<Expr>(Data.Id);
192
17
  if (E == nullptr)
193
1
    return llvm::make_error<StringError>(
194
1
        errc::invalid_argument, "Id not bound or not Expr: " + Data.Id);
195
16
  llvm::Optional<std::string> Source;
196
16
  switch (Data.Op) {
197
3
  case UnaryNodeOperator::Parens:
198
3
    Source = tooling::buildParens(*E, *Match.Context);
199
3
    break;
200
3
  case UnaryNodeOperator::Deref:
201
3
    Source = tooling::buildDereference(*E, *Match.Context);
202
3
    break;
203
4
  case UnaryNodeOperator::MaybeDeref:
204
4
    if (!E->getType()->isAnyPointerType()) {
205
1
      *Result += tooling::getText(*E, *Match.Context);
206
1
      return Error::success();
207
1
    }
208
3
    Source = tooling::buildDereference(*E, *Match.Context);
209
3
    break;
210
4
  case UnaryNodeOperator::AddressOf:
211
4
    Source = tooling::buildAddressOf(*E, *Match.Context);
212
4
    break;
213
2
  case UnaryNodeOperator::MaybeAddressOf:
214
2
    if (E->getType()->isAnyPointerType()) {
215
1
      *Result += tooling::getText(*E, *Match.Context);
216
1
      return Error::success();
217
1
    }
218
1
    Source = tooling::buildAddressOf(*E, *Match.Context);
219
1
    break;
220
14
  }
221
14
  if (!Source)
222
0
    return llvm::make_error<StringError>(
223
0
        errc::invalid_argument,
224
0
        "Could not construct expression source from ID: " + Data.Id);
225
14
  *Result += *Source;
226
14
  return Error::success();
227
14
}
228
229
Error evalData(const SelectorData &Data, const MatchFinder::MatchResult &Match,
230
10
               std::string *Result) {
231
10
  auto RawRange = Data.Selector(Match);
232
10
  if (!RawRange)
233
1
    return RawRange.takeError();
234
9
  CharSourceRange Range = Lexer::makeFileCharRange(
235
9
      *RawRange, *Match.SourceManager, Match.Context->getLangOpts());
236
9
  if (Range.isInvalid()) {
237
    // Validate the original range to attempt to get a meaningful error message.
238
    // If it's valid, then something else is the cause and we just return the
239
    // generic failure message.
240
1
    if (auto Err = tooling::validateEditRange(*RawRange, *Match.SourceManager))
241
1
      return handleErrors(std::move(Err), [](std::unique_ptr<StringError> E) {
242
1
        assert(E->convertToErrorCode() ==
243
1
                   llvm::make_error_code(errc::invalid_argument) &&
244
1
               "Validation errors must carry the invalid_argument code");
245
1
        return llvm::createStringError(
246
1
            errc::invalid_argument,
247
1
            "selected range could not be resolved to a valid source range; " +
248
1
                E->getMessage());
249
1
      });
250
0
    return llvm::createStringError(
251
0
        errc::invalid_argument,
252
0
        "selected range could not be resolved to a valid source range");
253
0
  }
254
  // Validate `Range`, because `makeFileCharRange` accepts some ranges that
255
  // `validateEditRange` rejects.
256
8
  if (auto Err = tooling::validateEditRange(Range, *Match.SourceManager))
257
0
    return joinErrors(
258
0
        llvm::createStringError(errc::invalid_argument,
259
0
                                "selected range is not valid for editing"),
260
0
        std::move(Err));
261
8
  *Result += tooling::getText(Range, *Match.Context);
262
8
  return Error::success();
263
8
}
264
265
Error evalData(const AccessData &Data, const MatchFinder::MatchResult &Match,
266
7
               std::string *Result) {
267
7
  const auto *E = Match.Nodes.getNodeAs<Expr>(Data.BaseId);
268
7
  if (E == nullptr)
269
0
    return llvm::make_error<StringError>(errc::invalid_argument,
270
0
                                         "Id not bound: " + Data.BaseId);
271
7
  if (!E->isImplicitCXXThis()) {
272
6
    if (llvm::Optional<std::string> S =
273
6
            E->getType()->isAnyPointerType()
274
6
                ? tooling::buildArrow(*E, *Match.Context)
275
6
                : tooling::buildDot(*E, *Match.Context))
276
6
      *Result += *S;
277
0
    else
278
0
      return llvm::make_error<StringError>(
279
0
          errc::invalid_argument,
280
0
          "Could not construct object text from ID: " + Data.BaseId);
281
7
  }
282
7
  return Data.Member->eval(Match, Result);
283
7
}
284
285
Error evalData(const IfBoundData &Data, const MatchFinder::MatchResult &Match,
286
2
               std::string *Result) {
287
2
  auto &M = Match.Nodes.getMap();
288
1
  return (M.find(Data.Id) != M.end() ? Data.TrueStencil : Data.FalseStencil)
289
2
      ->eval(Match, Result);
290
2
}
291
292
Error evalData(const MatchConsumer<std::string> &Fn,
293
1
               const MatchFinder::MatchResult &Match, std::string *Result) {
294
1
  Expected<std::string> Value = Fn(Match);
295
1
  if (!Value)
296
0
    return Value.takeError();
297
1
  *Result += *Value;
298
1
  return Error::success();
299
1
}
300
301
Error evalData(const SequenceData &Data, const MatchFinder::MatchResult &Match,
302
2
               std::string *Result) {
303
2
  for (const auto &S : Data.Stencils)
304
10
    if (auto Err = S->eval(Match, Result))
305
1
      return Err;
306
1
  return Error::success();
307
2
}
308
309
template <typename T> class StencilImpl : public StencilInterface {
310
  T Data;
311
312
public:
313
  template <typename... Ps>
314
175
  explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::RawTextData>::StencilImpl<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Line
Count
Source
314
114
  explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::SelectorData>::StencilImpl<std::__1::function<llvm::Expected<clang::CharSourceRange> (clang::ast_matchers::MatchFinder::MatchResult const&)> >(std::__1::function<llvm::Expected<clang::CharSourceRange> (clang::ast_matchers::MatchFinder::MatchResult const&)>&&)
Line
Count
Source
314
12
  explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::DebugPrintNodeData>::StencilImpl<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Line
Count
Source
314
1
  explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::UnaryOperationData>::StencilImpl<(anonymous namespace)::UnaryNodeOperator, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >((anonymous namespace)::UnaryNodeOperator&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&)
Line
Count
Source
314
20
  explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::AccessData>::StencilImpl<llvm::StringRef&, std::__1::shared_ptr<clang::transformer::MatchComputation<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(llvm::StringRef&, std::__1::shared_ptr<clang::transformer::MatchComputation<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&&)
Line
Count
Source
314
15
  explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::IfBoundData>::StencilImpl<llvm::StringRef&, std::__1::shared_ptr<clang::transformer::MatchComputation<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::shared_ptr<clang::transformer::MatchComputation<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >(llvm::StringRef&, std::__1::shared_ptr<clang::transformer::MatchComputation<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&&, std::__1::shared_ptr<clang::transformer::MatchComputation<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&&)
Line
Count
Source
314
5
  explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
Stencil.cpp:(anonymous namespace)::StencilImpl<std::__1::function<llvm::Expected<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > (clang::ast_matchers::MatchFinder::MatchResult const&)> >::StencilImpl<std::__1::function<llvm::Expected<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > (clang::ast_matchers::MatchFinder::MatchResult const&)> >(std::__1::function<llvm::Expected<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > (clang::ast_matchers::MatchFinder::MatchResult const&)>&&)
Line
Count
Source
314
2
  explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::SequenceData>::StencilImpl<std::__1::vector<std::__1::shared_ptr<clang::transformer::MatchComputation<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::allocator<std::__1::shared_ptr<clang::transformer::MatchComputation<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > > >(std::__1::vector<std::__1::shared_ptr<clang::transformer::MatchComputation<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, std::__1::allocator<std::__1::shared_ptr<clang::transformer::MatchComputation<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > >&&)
Line
Count
Source
314
6
  explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
315
316
  Error eval(const MatchFinder::MatchResult &Match,
317
141
             std::string *Result) const override {
318
141
    return evalData(Data, Match, Result);
319
141
  }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::RawTextData>::eval(clang::ast_matchers::MatchFinder::MatchResult const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const
Line
Count
Source
317
102
             std::string *Result) const override {
318
102
    return evalData(Data, Match, Result);
319
102
  }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::SelectorData>::eval(clang::ast_matchers::MatchFinder::MatchResult const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const
Line
Count
Source
317
10
             std::string *Result) const override {
318
10
    return evalData(Data, Match, Result);
319
10
  }
Unexecuted instantiation: Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::DebugPrintNodeData>::eval(clang::ast_matchers::MatchFinder::MatchResult const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::UnaryOperationData>::eval(clang::ast_matchers::MatchFinder::MatchResult const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const
Line
Count
Source
317
17
             std::string *Result) const override {
318
17
    return evalData(Data, Match, Result);
319
17
  }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::AccessData>::eval(clang::ast_matchers::MatchFinder::MatchResult const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const
Line
Count
Source
317
7
             std::string *Result) const override {
318
7
    return evalData(Data, Match, Result);
319
7
  }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::IfBoundData>::eval(clang::ast_matchers::MatchFinder::MatchResult const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const
Line
Count
Source
317
2
             std::string *Result) const override {
318
2
    return evalData(Data, Match, Result);
319
2
  }
Stencil.cpp:(anonymous namespace)::StencilImpl<std::__1::function<llvm::Expected<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > (clang::ast_matchers::MatchFinder::MatchResult const&)> >::eval(clang::ast_matchers::MatchFinder::MatchResult const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const
Line
Count
Source
317
1
             std::string *Result) const override {
318
1
    return evalData(Data, Match, Result);
319
1
  }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::SequenceData>::eval(clang::ast_matchers::MatchFinder::MatchResult const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const
Line
Count
Source
317
2
             std::string *Result) const override {
318
2
    return evalData(Data, Match, Result);
319
2
  }
320
321
40
  std::string toString() const override { return toStringData(Data); }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::RawTextData>::toString() const
Line
Count
Source
321
18
  std::string toString() const override { return toStringData(Data); }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::SelectorData>::toString() const
Line
Count
Source
321
2
  std::string toString() const override { return toStringData(Data); }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::DebugPrintNodeData>::toString() const
Line
Count
Source
321
1
  std::string toString() const override { return toStringData(Data); }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::UnaryOperationData>::toString() const
Line
Count
Source
321
3
  std::string toString() const override { return toStringData(Data); }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::AccessData>::toString() const
Line
Count
Source
321
8
  std::string toString() const override { return toStringData(Data); }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::IfBoundData>::toString() const
Line
Count
Source
321
3
  std::string toString() const override { return toStringData(Data); }
Stencil.cpp:(anonymous namespace)::StencilImpl<std::__1::function<llvm::Expected<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > (clang::ast_matchers::MatchFinder::MatchResult const&)> >::toString() const
Line
Count
Source
321
1
  std::string toString() const override { return toStringData(Data); }
Stencil.cpp:(anonymous namespace)::StencilImpl<(anonymous namespace)::SequenceData>::toString() const
Line
Count
Source
321
4
  std::string toString() const override { return toStringData(Data); }
322
};
323
} // namespace
324
325
114
Stencil transformer::detail::makeStencil(StringRef Text) {
326
114
  return std::make_shared<StencilImpl<RawTextData>>(std::string(Text));
327
114
}
328
329
12
Stencil transformer::detail::makeStencil(RangeSelector Selector) {
330
12
  return std::make_shared<StencilImpl<SelectorData>>(std::move(Selector));
331
12
}
332
333
1
Stencil transformer::dPrint(StringRef Id) {
334
1
  return std::make_shared<StencilImpl<DebugPrintNodeData>>(std::string(Id));
335
1
}
336
337
5
Stencil transformer::expression(llvm::StringRef Id) {
338
5
  return std::make_shared<StencilImpl<UnaryOperationData>>(
339
5
      UnaryNodeOperator::Parens, std::string(Id));
340
5
}
341
342
4
Stencil transformer::deref(llvm::StringRef ExprId) {
343
4
  return std::make_shared<StencilImpl<UnaryOperationData>>(
344
4
      UnaryNodeOperator::Deref, std::string(ExprId));
345
4
}
346
347
4
Stencil transformer::maybeDeref(llvm::StringRef ExprId) {
348
4
  return std::make_shared<StencilImpl<UnaryOperationData>>(
349
4
      UnaryNodeOperator::MaybeDeref, std::string(ExprId));
350
4
}
351
352
5
Stencil transformer::addressOf(llvm::StringRef ExprId) {
353
5
  return std::make_shared<StencilImpl<UnaryOperationData>>(
354
5
      UnaryNodeOperator::AddressOf, std::string(ExprId));
355
5
}
356
357
2
Stencil transformer::maybeAddressOf(llvm::StringRef ExprId) {
358
2
  return std::make_shared<StencilImpl<UnaryOperationData>>(
359
2
      UnaryNodeOperator::MaybeAddressOf, std::string(ExprId));
360
2
}
361
362
15
Stencil transformer::access(StringRef BaseId, Stencil Member) {
363
15
  return std::make_shared<StencilImpl<AccessData>>(BaseId, std::move(Member));
364
15
}
365
366
Stencil transformer::ifBound(StringRef Id, Stencil TrueStencil,
367
5
                             Stencil FalseStencil) {
368
5
  return std::make_shared<StencilImpl<IfBoundData>>(Id, std::move(TrueStencil),
369
5
                                                    std::move(FalseStencil));
370
5
}
371
372
2
Stencil transformer::run(MatchConsumer<std::string> Fn) {
373
2
  return std::make_shared<StencilImpl<MatchConsumer<std::string>>>(
374
2
      std::move(Fn));
375
2
}
376
377
105
Stencil transformer::catVector(std::vector<Stencil> Parts) {
378
  // Only one argument, so don't wrap in sequence.
379
105
  if (Parts.size() == 1)
380
99
    return std::move(Parts[0]);
381
6
  return std::make_shared<StencilImpl<SequenceData>>(std::move(Parts));
382
6
}