clang  14.0.0git
Stencil.cpp
Go to the documentation of this file.
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 
10 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/Expr.h"
16 #include "clang/Lex/Lexer.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 
32 using llvm::errc;
33 using llvm::Error;
34 using llvm::Expected;
35 using llvm::StringError;
36 
38  StringRef Id) {
39  auto &NodesMap = Nodes.getMap();
40  auto It = NodesMap.find(Id);
41  if (It == NodesMap.end())
42  return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
43  "Id not bound: " + Id);
44  return It->second;
45 }
46 
47 static Error printNode(StringRef Id, const MatchFinder::MatchResult &Match,
48  std::string *Result) {
49  std::string Output;
50  llvm::raw_string_ostream Os(Output);
51  auto NodeOrErr = getNode(Match.Nodes, Id);
52  if (auto Err = NodeOrErr.takeError())
53  return Err;
54  NodeOrErr->print(Os, PrintingPolicy(Match.Context->getLangOpts()));
55  *Result += Os.str();
56  return Error::success();
57 }
58 
59 // FIXME: Consider memoizing this function using the `ASTContext`.
60 static bool isSmartPointerType(QualType Ty, ASTContext &Context) {
61  using namespace ::clang::ast_matchers;
62 
63  // Optimization: hard-code common smart-pointer types. This can/should be
64  // removed if we start caching the results of this function.
65  auto KnownSmartPointer =
66  cxxRecordDecl(hasAnyName("::std::unique_ptr", "::std::shared_ptr"));
67  const auto QuacksLikeASmartPointer = cxxRecordDecl(
69  returns(qualType(pointsTo(type()))))),
71  returns(qualType(references(type()))))));
72  const auto SmartPointer = qualType(hasDeclaration(
73  cxxRecordDecl(anyOf(KnownSmartPointer, QuacksLikeASmartPointer))));
74  return match(SmartPointer, Ty, Context).size() > 0;
75 }
76 
77 // Identifies use of `operator*` on smart pointers, and returns the underlying
78 // smart-pointer expression; otherwise, returns null.
79 static const Expr *isSmartDereference(const Expr &E, ASTContext &Context) {
80  using namespace ::clang::ast_matchers;
81 
82  const auto HasOverloadedArrow = cxxRecordDecl(hasMethod(cxxMethodDecl(
83  hasOverloadedOperatorName("->"), returns(qualType(pointsTo(type()))))));
84  // Verify it is a smart pointer by finding `operator->` in the class
85  // declaration.
86  auto Deref = cxxOperatorCallExpr(
87  hasOverloadedOperatorName("*"), hasUnaryOperand(expr().bind("arg")),
88  callee(cxxMethodDecl(ofClass(HasOverloadedArrow))));
89  return selectFirst<Expr>("arg", match(Deref, E, Context));
90 }
91 
92 namespace {
93 // An arbitrary fragment of code within a stencil.
94 class RawTextStencil : public StencilInterface {
96 
97 public:
98  explicit RawTextStencil(std::string T) : Text(std::move(T)) {}
99 
100  std::string toString() const override {
101  std::string Result;
102  llvm::raw_string_ostream OS(Result);
103  OS << "\"";
104  OS.write_escaped(Text);
105  OS << "\"";
106  OS.flush();
107  return Result;
108  }
109 
110  Error eval(const MatchFinder::MatchResult &Match,
111  std::string *Result) const override {
112  Result->append(Text);
113  return Error::success();
114  }
115 };
116 
117 // A debugging operation to dump the AST for a particular (bound) AST node.
118 class DebugPrintNodeStencil : public StencilInterface {
119  std::string Id;
120 
121 public:
122  explicit DebugPrintNodeStencil(std::string S) : Id(std::move(S)) {}
123 
124  std::string toString() const override {
125  return (llvm::Twine("dPrint(\"") + Id + "\")").str();
126  }
127 
128  Error eval(const MatchFinder::MatchResult &Match,
129  std::string *Result) const override {
130  return printNode(Id, Match, Result);
131  }
132 };
133 
134 // Operators that take a single node Id as an argument.
135 enum class UnaryNodeOperator {
136  Parens,
137  Deref,
138  MaybeDeref,
139  AddressOf,
140  MaybeAddressOf,
141  Describe,
142 };
143 
144 // Generic container for stencil operations with a (single) node-id argument.
145 class UnaryOperationStencil : public StencilInterface {
146  UnaryNodeOperator Op;
147  std::string Id;
148 
149 public:
150  UnaryOperationStencil(UnaryNodeOperator Op, std::string Id)
151  : Op(Op), Id(std::move(Id)) {}
152 
153  std::string toString() const override {
154  StringRef OpName;
155  switch (Op) {
156  case UnaryNodeOperator::Parens:
157  OpName = "expression";
158  break;
159  case UnaryNodeOperator::Deref:
160  OpName = "deref";
161  break;
162  case UnaryNodeOperator::MaybeDeref:
163  OpName = "maybeDeref";
164  break;
165  case UnaryNodeOperator::AddressOf:
166  OpName = "addressOf";
167  break;
168  case UnaryNodeOperator::MaybeAddressOf:
169  OpName = "maybeAddressOf";
170  break;
171  case UnaryNodeOperator::Describe:
172  OpName = "describe";
173  break;
174  }
175  return (OpName + "(\"" + Id + "\")").str();
176  }
177 
178  Error eval(const MatchFinder::MatchResult &Match,
179  std::string *Result) const override {
180  // The `Describe` operation can be applied to any node, not just
181  // expressions, so it is handled here, separately.
182  if (Op == UnaryNodeOperator::Describe)
183  return printNode(Id, Match, Result);
184 
185  const auto *E = Match.Nodes.getNodeAs<Expr>(Id);
186  if (E == nullptr)
187  return llvm::make_error<StringError>(errc::invalid_argument,
188  "Id not bound or not Expr: " + Id);
190  switch (Op) {
191  case UnaryNodeOperator::Parens:
192  Source = tooling::buildParens(*E, *Match.Context);
193  break;
194  case UnaryNodeOperator::Deref:
195  Source = tooling::buildDereference(*E, *Match.Context);
196  break;
197  case UnaryNodeOperator::MaybeDeref:
198  if (E->getType()->isAnyPointerType() ||
199  isSmartPointerType(E->getType(), *Match.Context)) {
200  // Strip off any operator->. This can only occur inside an actual arrow
201  // member access, so we treat it as equivalent to an actual object
202  // expression.
203  if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
204  if (OpCall->getOperator() == clang::OO_Arrow &&
205  OpCall->getNumArgs() == 1) {
206  E = OpCall->getArg(0);
207  }
208  }
209  Source = tooling::buildDereference(*E, *Match.Context);
210  break;
211  }
212  *Result += tooling::getText(*E, *Match.Context);
213  return Error::success();
214  case UnaryNodeOperator::AddressOf:
215  Source = tooling::buildAddressOf(*E, *Match.Context);
216  break;
217  case UnaryNodeOperator::MaybeAddressOf:
218  if (E->getType()->isAnyPointerType() ||
219  isSmartPointerType(E->getType(), *Match.Context)) {
220  // Strip off any operator->. This can only occur inside an actual arrow
221  // member access, so we treat it as equivalent to an actual object
222  // expression.
223  if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
224  if (OpCall->getOperator() == clang::OO_Arrow &&
225  OpCall->getNumArgs() == 1) {
226  E = OpCall->getArg(0);
227  }
228  }
229  *Result += tooling::getText(*E, *Match.Context);
230  return Error::success();
231  }
232  Source = tooling::buildAddressOf(*E, *Match.Context);
233  break;
234  case UnaryNodeOperator::Describe:
235  llvm_unreachable("This case is handled at the start of the function");
236  }
237  if (!Source)
238  return llvm::make_error<StringError>(
239  errc::invalid_argument,
240  "Could not construct expression source from ID: " + Id);
241  *Result += *Source;
242  return Error::success();
243  }
244 };
245 
246 // The fragment of code corresponding to the selected range.
247 class SelectorStencil : public StencilInterface {
249 
250 public:
251  explicit SelectorStencil(RangeSelector S) : Selector(std::move(S)) {}
252 
253  std::string toString() const override { return "selection(...)"; }
254 
255  Error eval(const MatchFinder::MatchResult &Match,
256  std::string *Result) const override {
257  auto RawRange = Selector(Match);
258  if (!RawRange)
259  return RawRange.takeError();
261  *RawRange, *Match.SourceManager, Match.Context->getLangOpts());
262  if (Range.isInvalid()) {
263  // Validate the original range to attempt to get a meaningful error
264  // message. If it's valid, then something else is the cause and we just
265  // return the generic failure message.
266  if (auto Err =
267  tooling::validateEditRange(*RawRange, *Match.SourceManager))
268  return handleErrors(std::move(Err), [](std::unique_ptr<StringError> E) {
269  assert(E->convertToErrorCode() ==
270  llvm::make_error_code(errc::invalid_argument) &&
271  "Validation errors must carry the invalid_argument code");
272  return llvm::createStringError(
273  errc::invalid_argument,
274  "selected range could not be resolved to a valid source range; " +
275  E->getMessage());
276  });
277  return llvm::createStringError(
278  errc::invalid_argument,
279  "selected range could not be resolved to a valid source range");
280  }
281  // Validate `Range`, because `makeFileCharRange` accepts some ranges that
282  // `validateEditRange` rejects.
283  if (auto Err = tooling::validateEditRange(Range, *Match.SourceManager))
284  return joinErrors(
285  llvm::createStringError(errc::invalid_argument,
286  "selected range is not valid for editing"),
287  std::move(Err));
288  *Result += tooling::getText(Range, *Match.Context);
289  return Error::success();
290  }
291 };
292 
293 // A stencil operation to build a member access `e.m` or `e->m`, as appropriate.
294 class AccessStencil : public StencilInterface {
295  std::string BaseId;
296  Stencil Member;
297 
298 public:
299  AccessStencil(StringRef BaseId, Stencil Member)
300  : BaseId(std::string(BaseId)), Member(std::move(Member)) {}
301 
302  std::string toString() const override {
303  return (llvm::Twine("access(\"") + BaseId + "\", " + Member->toString() +
304  ")")
305  .str();
306  }
307 
308  Error eval(const MatchFinder::MatchResult &Match,
309  std::string *Result) const override {
310  const auto *E = Match.Nodes.getNodeAs<Expr>(BaseId);
311  if (E == nullptr)
312  return llvm::make_error<StringError>(errc::invalid_argument,
313  "Id not bound: " + BaseId);
314  if (!E->isImplicitCXXThis()) {
316  if (E->getType()->isAnyPointerType() ||
317  isSmartPointerType(E->getType(), *Match.Context)) {
318  // Strip off any operator->. This can only occur inside an actual arrow
319  // member access, so we treat it as equivalent to an actual object
320  // expression.
321  if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
322  if (OpCall->getOperator() == clang::OO_Arrow &&
323  OpCall->getNumArgs() == 1) {
324  E = OpCall->getArg(0);
325  }
326  }
327  S = tooling::buildArrow(*E, *Match.Context);
328  } else if (const auto *Operand = isSmartDereference(*E, *Match.Context)) {
329  // `buildDot` already handles the built-in dereference operator, so we
330  // only need to catch overloaded `operator*`.
331  S = tooling::buildArrow(*Operand, *Match.Context);
332  } else {
333  S = tooling::buildDot(*E, *Match.Context);
334  }
335  if (S.hasValue())
336  *Result += *S;
337  else
338  return llvm::make_error<StringError>(
339  errc::invalid_argument,
340  "Could not construct object text from ID: " + BaseId);
341  }
342  return Member->eval(Match, Result);
343  }
344 };
345 
346 class IfBoundStencil : public StencilInterface {
347  std::string Id;
348  Stencil TrueStencil;
349  Stencil FalseStencil;
350 
351 public:
352  IfBoundStencil(StringRef Id, Stencil TrueStencil, Stencil FalseStencil)
353  : Id(std::string(Id)), TrueStencil(std::move(TrueStencil)),
354  FalseStencil(std::move(FalseStencil)) {}
355 
356  std::string toString() const override {
357  return (llvm::Twine("ifBound(\"") + Id + "\", " + TrueStencil->toString() +
358  ", " + FalseStencil->toString() + ")")
359  .str();
360  }
361 
362  Error eval(const MatchFinder::MatchResult &Match,
363  std::string *Result) const override {
364  auto &M = Match.Nodes.getMap();
365  return (M.find(Id) != M.end() ? TrueStencil : FalseStencil)
366  ->eval(Match, Result);
367  }
368 };
369 
370 class SelectBoundStencil : public clang::transformer::StencilInterface {
371  static bool containsNoNullStencils(
372  const std::vector<std::pair<std::string, Stencil>> &Cases) {
373  for (const auto &S : Cases)
374  if (S.second == nullptr)
375  return false;
376  return true;
377  }
378 
379 public:
380  SelectBoundStencil(std::vector<std::pair<std::string, Stencil>> Cases,
381  Stencil Default)
382  : CaseStencils(std::move(Cases)), DefaultStencil(std::move(Default)) {
383  assert(containsNoNullStencils(CaseStencils) &&
384  "cases of selectBound may not be null");
385  }
386  ~SelectBoundStencil() override{};
387 
388  llvm::Error eval(const MatchFinder::MatchResult &match,
389  std::string *result) const override {
390  const BoundNodes::IDToNodeMap &NodeMap = match.Nodes.getMap();
391  for (const auto &S : CaseStencils) {
392  if (NodeMap.count(S.first) > 0) {
393  return S.second->eval(match, result);
394  }
395  }
396 
397  if (DefaultStencil != nullptr) {
398  return DefaultStencil->eval(match, result);
399  }
400 
402  CaseIDs.reserve(CaseStencils.size());
403  for (const auto &S : CaseStencils)
404  CaseIDs.emplace_back(S.first);
405 
406  return llvm::createStringError(
407  errc::result_out_of_range,
408  llvm::Twine("selectBound failed: no cases bound and no default: {") +
409  llvm::join(CaseIDs, ", ") + "}");
410  }
411 
412  std::string toString() const override {
413  std::string Buffer;
414  llvm::raw_string_ostream Stream(Buffer);
415  Stream << "selectBound({";
416  bool First = true;
417  for (const auto &S : CaseStencils) {
418  if (First)
419  First = false;
420  else
421  Stream << "}, ";
422  Stream << "{\"" << S.first << "\", " << S.second->toString();
423  }
424  Stream << "}}";
425  if (DefaultStencil != nullptr) {
426  Stream << ", " << DefaultStencil->toString();
427  }
428  Stream << ")";
429  return Stream.str();
430  }
431 
432 private:
433  std::vector<std::pair<std::string, Stencil>> CaseStencils;
434  Stencil DefaultStencil;
435 };
436 
437 class SequenceStencil : public StencilInterface {
438  std::vector<Stencil> Stencils;
439 
440 public:
441  SequenceStencil(std::vector<Stencil> Stencils)
442  : Stencils(std::move(Stencils)) {}
443 
444  std::string toString() const override {
446  Parts.reserve(Stencils.size());
447  for (const auto &S : Stencils)
448  Parts.push_back(S->toString());
449  return (llvm::Twine("seq(") + llvm::join(Parts, ", ") + ")").str();
450  }
451 
452  Error eval(const MatchFinder::MatchResult &Match,
453  std::string *Result) const override {
454  for (const auto &S : Stencils)
455  if (auto Err = S->eval(Match, Result))
456  return Err;
457  return Error::success();
458  }
459 };
460 
461 class RunStencil : public StencilInterface {
463 
464 public:
465  explicit RunStencil(MatchConsumer<std::string> C) : Consumer(std::move(C)) {}
466 
467  std::string toString() const override { return "run(...)"; }
468 
469  Error eval(const MatchFinder::MatchResult &Match,
470  std::string *Result) const override {
471 
472  Expected<std::string> Value = Consumer(Match);
473  if (!Value)
474  return Value.takeError();
475  *Result += *Value;
476  return Error::success();
477  }
478 };
479 } // namespace
480 
482  return std::make_shared<RawTextStencil>(std::string(Text));
483 }
484 
486  return std::make_shared<SelectorStencil>(std::move(Selector));
487 }
488 
489 Stencil transformer::dPrint(StringRef Id) {
490  return std::make_shared<DebugPrintNodeStencil>(std::string(Id));
491 }
492 
494  return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::Parens,
495  std::string(Id));
496 }
497 
498 Stencil transformer::deref(llvm::StringRef ExprId) {
499  return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::Deref,
500  std::string(ExprId));
501 }
502 
503 Stencil transformer::maybeDeref(llvm::StringRef ExprId) {
504  return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::MaybeDeref,
505  std::string(ExprId));
506 }
507 
508 Stencil transformer::addressOf(llvm::StringRef ExprId) {
509  return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::AddressOf,
510  std::string(ExprId));
511 }
512 
513 Stencil transformer::maybeAddressOf(llvm::StringRef ExprId) {
514  return std::make_shared<UnaryOperationStencil>(
515  UnaryNodeOperator::MaybeAddressOf, std::string(ExprId));
516 }
517 
518 Stencil transformer::describe(StringRef Id) {
519  return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::Describe,
520  std::string(Id));
521 }
522 
523 Stencil transformer::access(StringRef BaseId, Stencil Member) {
524  return std::make_shared<AccessStencil>(BaseId, std::move(Member));
525 }
526 
527 Stencil transformer::ifBound(StringRef Id, Stencil TrueStencil,
528  Stencil FalseStencil) {
529  return std::make_shared<IfBoundStencil>(Id, std::move(TrueStencil),
530  std::move(FalseStencil));
531 }
532 
534  std::vector<std::pair<std::string, Stencil>> CaseStencils,
535  Stencil DefaultStencil) {
536  return std::make_shared<SelectBoundStencil>(std::move(CaseStencils),
537  std::move(DefaultStencil));
538 }
539 
541  return std::make_shared<RunStencil>(std::move(Fn));
542 }
543 
544 Stencil transformer::catVector(std::vector<Stencil> Parts) {
545  // Only one argument, so don't wrap in sequence.
546  if (Parts.size() == 1)
547  return std::move(Parts[0]);
548  return std::make_shared<SequenceStencil>(std::move(Parts));
549 }
clang::index::SymbolRole::AddressOf
@ AddressOf
isSmartDereference
static const Expr * isSmartDereference(const Expr &E, ASTContext &Context)
Definition: Stencil.cpp:79
clang::Lexer::makeFileCharRange
static CharSourceRange makeFileCharRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Accepts a range and returns a character range with file locations.
Definition: Lexer.cpp:888
clang::tooling::buildDot
llvm::Optional< std::string > buildDot(const Expr &E, const ASTContext &Context)
Adds a dot to the end of the given expression, but adds parentheses when needed by the syntax,...
Definition: SourceCodeBuilders.cpp:117
clang::ast_matchers::hasAnyName
const internal::VariadicFunction< internal::Matcher< NamedDecl >, StringRef, internal::hasAnyNameFunc > hasAnyName
Matches NamedDecl nodes that have any of the specified names.
Definition: ASTMatchersInternal.cpp:996
clang::transformer::describe
Stencil describe(llvm::StringRef Id)
Produces a human-readable rendering of the node bound to Id, suitable for diagnostics and debugging.
Nodes
BoundNodesTreeBuilder Nodes
Definition: ASTMatchFinder.cpp:82
Error
llvm::Error Error
Definition: ByteCodeEmitter.cpp:20
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::transformer::access
Stencil access(llvm::StringRef BaseId, Stencil Member)
Constructs a MemberExpr that accesses the named member (Member) of the object bound to BaseId.
clang::ast_matchers::anyOf
const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits< unsigned >::max()> anyOf
Matches if any of the given matchers matches.
Definition: ASTMatchersInternal.cpp:988
llvm::SmallVector
Definition: LLVM.h:38
clang::ast_matchers::MatchFinder
A class to allow finding matches over the Clang AST.
Definition: ASTMatchFinder.h:68
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:673
AttributeLangSupport::C
@ C
Definition: SemaDeclAttr.cpp:54
clang::tooling::buildArrow
llvm::Optional< std::string > buildArrow(const Expr &E, const ASTContext &Context)
Adds an arrow to the end of the given expression, but adds parentheses when needed by the syntax,...
Definition: SourceCodeBuilders.cpp:141
clang::ast_matchers::type
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
Definition: ASTMatchersInternal.cpp:772
clang::transformer::run
Stencil run(MatchConsumer< std::string > C)
Wraps a MatchConsumer in a Stencil, so that it can be used in a Stencil.
Definition: Stencil.cpp:540
clang::transformer::selectBound
Stencil selectBound(std::vector< std::pair< std::string, Stencil >> CaseStencils, Stencil DefaultStencil=nullptr)
Chooses between multiple stencils, based on the presence of bound nodes.
Definition: Stencil.cpp:533
clang::transformer::deref
Stencil deref(llvm::StringRef ExprId)
Constructs an idiomatic dereferencing of the expression bound to ExprId.
Definition: Stencil.cpp:498
llvm::Optional< std::string >
clang::transformer::Stencil
std::shared_ptr< StencilInterface > Stencil
A sequence of code fragments, references to parameters and code-generation operations that together c...
Definition: Stencil.h:46
clang::ComparisonCategoryType::First
@ First
llvm::Expected
Definition: LLVM.h:41
ASTMatchFinder.h
clang::PrintingPolicy
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:59
clang::transformer::detail::makeStencil
Stencil makeStencil(llvm::StringRef Text)
Convenience function to construct a Stencil.
clang::transformer::RangeSelector
MatchConsumer< CharSourceRange > RangeSelector
Definition: RangeSelector.h:27
clang::StructuralEquivalenceKind::Default
@ Default
Expected
llvm::Expected< T > Expected
Definition: ByteCodeExprGen.cpp:22
clang::transformer::addressOf
Stencil addressOf(llvm::StringRef ExprId)
Constructs an expression that idiomatically takes the address of the expression bound to ExprId.
Definition: Stencil.cpp:508
clang::ast_matchers::cxxOperatorCallExpr
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXOperatorCallExpr > cxxOperatorCallExpr
Matches overloaded operator calls.
Definition: ASTMatchersInternal.cpp:886
clang::ast_matchers::expr
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
Definition: ASTMatchersInternal.cpp:889
printNode
static Error printNode(StringRef Id, const MatchFinder::MatchResult &Match, std::string *Result)
Definition: Stencil.cpp:47
clang::ast_matchers
Definition: ASTMatchers.h:98
clang::transformer::maybeDeref
Stencil maybeDeref(llvm::StringRef ExprId)
If ExprId is of pointer type, constructs an idiomatic dereferencing of the expression bound to ExprId...
Definition: Stencil.cpp:503
clang::tooling::buildParens
llvm::Optional< std::string > buildParens(const Expr &E, const ASTContext &Context)
Builds source for an expression, adding parens if needed for unambiguous parsing.
Definition: SourceCodeBuilders.cpp:63
Id
int Id
Definition: ASTDiff.cpp:191
clang::threadSafety::sx::toString
std::string toString(const til::SExpr *E)
Definition: ThreadSafetyCommon.h:89
clang::tooling::buildAddressOf
llvm::Optional< std::string > buildAddressOf(const Expr &E, const ASTContext &Context)
Builds idiomatic source for taking the address of E: prefix with & but simplify when it already begin...
Definition: SourceCodeBuilders.cpp:94
clang::ASTContext
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:212
ASTMatchers.h
clang::DeclaratorContext::Member
@ Member
SourceCodeBuilders.h
clang::ast_matchers::cxxMethodDecl
const internal::VariadicDynCastAllOfMatcher< Decl, CXXMethodDecl > cxxMethodDecl
Matches method declarations.
Definition: ASTMatchersInternal.cpp:798
clang::transformer::maybeAddressOf
Stencil maybeAddressOf(llvm::StringRef ExprId)
If ExprId is not a pointer type, constructs an expression that idiomatically takes the address of the...
Definition: Stencil.cpp:513
Expr.h
ASTContext.h
clang::transformer::MatchComputation
A failable computation over nodes bound by AST matchers, with (limited) reflection via the toString m...
Definition: MatchConsumer.h:64
BoundNodes
BoundNodesTreeBuilder BoundNodes
Definition: ASTMatchFinder.cpp:68
clang::transformer::EditKind::Range
@ Range
clang::tooling::buildDereference
llvm::Optional< std::string > buildDereference(const Expr &E, const ASTContext &Context)
Builds idiomatic source for the dereferencing of E: prefix with * but simplify when it already begins...
Definition: SourceCodeBuilders.cpp:74
SourceLocation.h
clang::transformer::expression
Stencil expression(llvm::StringRef Id)
Generates the source of the expression bound to Id, wrapping it in parentheses if it may parse differ...
Definition: Stencil.cpp:493
SourceCode.h
clang::tooling::validateEditRange
llvm::Error validateEditRange(const CharSourceRange &Range, const SourceManager &SM)
Determines whether Range is one that can be edited by a rewrite; generally, one that starts and ends ...
Definition: SourceCode.cpp:53
Lexer.h
Value
Value
Definition: UninitializedValues.cpp:102
clang::CharSourceRange
Represents a character-granular source range.
Definition: SourceLocation.h:255
Stencil.h
clang::transformer::MatchConsumer
std::function< Expected< T >(const ast_matchers::MatchFinder::MatchResult &)> MatchConsumer
A failable computation over nodes bound by AST matchers.
Definition: MatchConsumer.h:35
clang::ast_matchers::MatchFinder::MatchResult::Context
clang::ASTContext *const Context
Utilities for interpreting the matched AST structures.
Definition: ASTMatchFinder.h:84
ASTTypeTraits.h
clang::ast_matchers::MatchFinder::MatchResult
Contains all information for a given match.
Definition: ASTMatchFinder.h:74
clang::ast_matchers::BoundNodes::getMap
const IDToNodeMap & getMap() const
Retrieve mapping from binding identifiers to bound nodes.
Definition: ASTMatchers.h:124
std
Definition: Format.h:4034
clang::ast_matchers::BoundNodes::IDToNodeMap
internal::BoundNodesMap::IDToNodeMap IDToNodeMap
Type of mapping from binding identifiers to bound nodes.
Definition: ASTMatchers.h:121
clang::transformer::ifBound
MatchConsumer< T > ifBound(std::string ID, MatchConsumer< T > TrueC, MatchConsumer< T > FalseC)
Chooses between the two consumers, based on whether ID is bound in the match.
Definition: MatchConsumer.h:47
clang::ast_matchers::MatchFinder::MatchResult::Nodes
const BoundNodes Nodes
Contains the nodes bound on the current match.
Definition: ASTMatchFinder.h:80
clang::ast_matchers::BoundNodes::getNodeAs
const T * getNodeAs(StringRef ID) const
Returns the AST node bound to ID.
Definition: ASTMatchers.h:114
clang
Definition: CalledOnceCheck.h:17
Text
StringRef Text
Definition: Format.cpp:2334
clang::Selector
Smart pointer class that efficiently represents Objective-C method names.
Definition: IdentifierTable.h:748
clang::ast_matchers::match
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
Definition: ASTMatchFinder.h:312
clang::tooling::getText
StringRef getText(CharSourceRange Range, const ASTContext &Context)
Returns the source-code text in the specified range.
Definition: SourceCode.cpp:31
getNode
static llvm::Expected< DynTypedNode > getNode(const BoundNodes &Nodes, StringRef Id)
Definition: Stencil.cpp:37
clang::ast_matchers::BoundNodes
Maps string IDs to AST nodes matched by parts of a matcher.
Definition: ASTMatchers.h:107
clang::ast_matchers::cxxRecordDecl
const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl
Matches C++ class declarations.
Definition: ASTMatchersInternal.cpp:745
clang::ast_matchers::MatchFinder::MatchResult::SourceManager
clang::SourceManager *const SourceManager
Definition: ASTMatchFinder.h:85
clang::Expr
This represents one expression.
Definition: Expr.h:109
clang::format::make_error_code
std::error_code make_error_code(ParseError e)
Definition: Format.cpp:907
isSmartPointerType
static bool isSmartPointerType(QualType Ty, ASTContext &Context)
Definition: Stencil.cpp:60
clang::ast_matchers::hasDeclaration
internal::PolymorphicMatcher< internal::HasDeclarationMatcher, void(internal::HasDeclarationSupportedTypes), internal::Matcher< Decl > > hasDeclaration(const internal::Matcher< Decl > &InnerMatcher)
Matches a node if the declaration associated with that node matches the given matcher.
Definition: ASTMatchers.h:3563
clang::transformer::catVector
Stencil catVector(std::vector< Stencil > Parts)
Constructs the string representing the concatenation of the given Parts.
Definition: Stencil.cpp:544
clang::transformer::dPrint
Stencil dPrint(llvm::StringRef Id)
For debug use only; semantics are not guaranteed.
clang::ast_matchers::hasOverloadedOperatorName
internal::PolymorphicMatcher< internal::HasOverloadedOperatorNameMatcher, AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl), std::vector< std::string > > hasOverloadedOperatorName(StringRef Name)
Matches overloaded operator names.
Definition: ASTMatchers.h:3052
clang::ASTContext::getLangOpts
const LangOptions & getLangOpts() const
Definition: ASTContext.h:765
clang::ento::ObjKind::OS
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
clang::ast_matchers::qualType
const internal::VariadicAllOfMatcher< QualType > qualType
Matches QualTypes in the clang AST.
Definition: ASTMatchersInternal.cpp:771