Bug Summary

File:build/source/clang/include/clang/Tooling/Transformer/RewriteRule.h
Warning:line 174, column 1
Potential memory leak

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name RewriteRule.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -D CLANG_REPOSITORY_STRING="++20230510111145+7df43bdb42ae-1~exp1~20230510111303.1288" -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/clang/lib/Tooling/Transformer -I /build/source/clang/lib/Tooling/Transformer -I /build/source/clang/include -I tools/clang/include -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/clang/lib/Tooling/Transformer/RewriteRule.cpp

/build/source/clang/lib/Tooling/Transformer/RewriteRule.cpp

1//===--- Transformer.cpp - Transformer library 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/RewriteRule.h"
10#include "clang/AST/ASTTypeTraits.h"
11#include "clang/AST/Stmt.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13#include "clang/ASTMatchers/ASTMatchers.h"
14#include "clang/Basic/SourceLocation.h"
15#include "clang/Tooling/Transformer/SourceCode.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/Support/Errc.h"
18#include "llvm/Support/Error.h"
19#include <map>
20#include <string>
21#include <utility>
22#include <vector>
23
24using namespace clang;
25using namespace transformer;
26
27using ast_matchers::MatchFinder;
28using ast_matchers::internal::DynTypedMatcher;
29
30using MatchResult = MatchFinder::MatchResult;
31
32const char transformer::RootID[] = "___root___";
33
34static Expected<SmallVector<transformer::Edit, 1>>
35translateEdits(const MatchResult &Result, ArrayRef<ASTEdit> ASTEdits) {
36 SmallVector<transformer::Edit, 1> Edits;
37 for (const auto &E : ASTEdits) {
38 Expected<CharSourceRange> Range = E.TargetRange(Result);
39 if (!Range)
40 return Range.takeError();
41 std::optional<CharSourceRange> EditRange =
42 tooling::getFileRangeForEdit(*Range, *Result.Context);
43 // FIXME: let user specify whether to treat this case as an error or ignore
44 // it as is currently done. This behavior is problematic in that it hides
45 // failures from bad ranges. Also, the behavior here differs from
46 // `flatten`. Here, we abort (without error), whereas flatten, if it hits an
47 // empty list, does not abort. As a result, `editList({A,B})` is not
48 // equivalent to `flatten(edit(A), edit(B))`. The former will abort if `A`
49 // produces a bad range, whereas the latter will simply ignore A.
50 if (!EditRange)
51 return SmallVector<Edit, 0>();
52 transformer::Edit T;
53 T.Kind = E.Kind;
54 T.Range = *EditRange;
55 if (E.Replacement) {
56 auto Replacement = E.Replacement->eval(Result);
57 if (!Replacement)
58 return Replacement.takeError();
59 T.Replacement = std::move(*Replacement);
60 }
61 if (E.Note) {
62 auto Note = E.Note->eval(Result);
63 if (!Note)
64 return Note.takeError();
65 T.Note = std::move(*Note);
66 }
67 if (E.Metadata) {
68 auto Metadata = E.Metadata(Result);
69 if (!Metadata)
70 return Metadata.takeError();
71 T.Metadata = std::move(*Metadata);
72 }
73 Edits.push_back(std::move(T));
74 }
75 return Edits;
76}
77
78EditGenerator transformer::editList(SmallVector<ASTEdit, 1> Edits) {
79 return [Edits = std::move(Edits)](const MatchResult &Result) {
80 return translateEdits(Result, Edits);
81 };
82}
83
84EditGenerator transformer::edit(ASTEdit Edit) {
85 return [Edit = std::move(Edit)](const MatchResult &Result) {
5
Calling constructor for 'function<llvm::Expected<llvm::SmallVector<clang::transformer::Edit, 1>> (const clang::ast_matchers::MatchFinder::MatchResult &)>'
12
Returning from constructor for 'function<llvm::Expected<llvm::SmallVector<clang::transformer::Edit, 1>> (const clang::ast_matchers::MatchFinder::MatchResult &)>'
86 return translateEdits(Result, {Edit});
87 };
88}
89
90EditGenerator transformer::noopEdit(RangeSelector Anchor) {
91 return [Anchor = std::move(Anchor)](const MatchResult &Result)
92 -> Expected<SmallVector<transformer::Edit, 1>> {
93 Expected<CharSourceRange> Range = Anchor(Result);
94 if (!Range)
95 return Range.takeError();
96 // In case the range is inside a macro expansion, map the location back to a
97 // "real" source location.
98 SourceLocation Begin =
99 Result.SourceManager->getSpellingLoc(Range->getBegin());
100 Edit E;
101 // Implicitly, leave `E.Replacement` as the empty string.
102 E.Kind = EditKind::Range;
103 E.Range = CharSourceRange::getCharRange(Begin, Begin);
104 return SmallVector<Edit, 1>{E};
105 };
106}
107
108EditGenerator
109transformer::flattenVector(SmallVector<EditGenerator, 2> Generators) {
110 if (Generators.size() == 1)
111 return std::move(Generators[0]);
112 return
113 [Gs = std::move(Generators)](
114 const MatchResult &Result) -> llvm::Expected<SmallVector<Edit, 1>> {
115 SmallVector<Edit, 1> AllEdits;
116 for (const auto &G : Gs) {
117 llvm::Expected<SmallVector<Edit, 1>> Edits = G(Result);
118 if (!Edits)
119 return Edits.takeError();
120 AllEdits.append(Edits->begin(), Edits->end());
121 }
122 return AllEdits;
123 };
124}
125
126ASTEdit transformer::changeTo(RangeSelector Target, TextGenerator Replacement) {
127 ASTEdit E;
128 E.TargetRange = std::move(Target);
129 E.Replacement = std::move(Replacement);
130 return E;
131}
132
133ASTEdit transformer::note(RangeSelector Anchor, TextGenerator Note) {
134 ASTEdit E;
135 E.TargetRange = transformer::before(Anchor);
136 E.Note = std::move(Note);
137 return E;
138}
139
140namespace {
141/// A \c TextGenerator that always returns a fixed string.
142class SimpleTextGenerator : public MatchComputation<std::string> {
143 std::string S;
144
145public:
146 SimpleTextGenerator(std::string S) : S(std::move(S)) {}
147 llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &,
148 std::string *Result) const override {
149 Result->append(S);
150 return llvm::Error::success();
151 }
152 std::string toString() const override {
153 return (llvm::Twine("text(\"") + S + "\")").str();
154 }
155};
156} // namespace
157
158static TextGenerator makeText(std::string S) {
159 return std::make_shared<SimpleTextGenerator>(std::move(S));
160}
161
162ASTEdit transformer::remove(RangeSelector S) {
163 return change(std::move(S), makeText(""));
164}
165
166static std::string formatHeaderPath(StringRef Header, IncludeFormat Format) {
167 switch (Format) {
168 case transformer::IncludeFormat::Quoted:
169 return Header.str();
170 case transformer::IncludeFormat::Angled:
171 return ("<" + Header + ">").str();
172 }
173 llvm_unreachable("Unknown transformer::IncludeFormat enum")::llvm::llvm_unreachable_internal("Unknown transformer::IncludeFormat enum"
, "clang/lib/Tooling/Transformer/RewriteRule.cpp", 173)
;
174}
175
176ASTEdit transformer::addInclude(RangeSelector Target, StringRef Header,
177 IncludeFormat Format) {
178 ASTEdit E;
179 E.Kind = EditKind::AddInclude;
180 E.TargetRange = Target;
181 E.Replacement = makeText(formatHeaderPath(Header, Format));
182 return E;
183}
184
185EditGenerator
186transformer::detail::makeEditGenerator(llvm::SmallVector<ASTEdit, 1> Edits) {
187 return editList(std::move(Edits));
188}
189
190EditGenerator transformer::detail::makeEditGenerator(ASTEdit Edit) {
191 return edit(std::move(Edit));
192}
193
194RewriteRule transformer::detail::makeRule(DynTypedMatcher M,
195 EditGenerator Edits) {
196 RewriteRule R;
197 R.Cases = {{std::move(M), std::move(Edits)}};
198 return R;
199}
200
201RewriteRule transformer::makeRule(ast_matchers::internal::DynTypedMatcher M,
202 std::initializer_list<ASTEdit> Edits) {
203 return detail::makeRule(std::move(M),
204 detail::makeEditGenerator(std::move(Edits)));
205}
206
207namespace {
208
209/// Unconditionally binds the given node set before trying `InnerMatcher` and
210/// keeps the bound nodes on a successful match.
211template <typename T>
212class BindingsMatcher : public ast_matchers::internal::MatcherInterface<T> {
213 ast_matchers::BoundNodes Nodes;
214 const ast_matchers::internal::Matcher<T> InnerMatcher;
215
216public:
217 explicit BindingsMatcher(ast_matchers::BoundNodes Nodes,
218 ast_matchers::internal::Matcher<T> InnerMatcher)
219 : Nodes(std::move(Nodes)), InnerMatcher(std::move(InnerMatcher)) {}
220
221 bool matches(
222 const T &Node, ast_matchers::internal::ASTMatchFinder *Finder,
223 ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
224 ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
225 for (const auto &N : Nodes.getMap())
226 Result.setBinding(N.first, N.second);
227 if (InnerMatcher.matches(Node, Finder, &Result)) {
228 *Builder = std::move(Result);
229 return true;
230 }
231 return false;
232 }
233};
234
235/// Matches nodes of type T that have at least one descendant node for which the
236/// given inner matcher matches. Will match for each descendant node that
237/// matches. Based on ForEachDescendantMatcher, but takes a dynamic matcher,
238/// instead of a static one, because it is used by RewriteRule, which carries
239/// (only top-level) dynamic matchers.
240template <typename T>
241class DynamicForEachDescendantMatcher
242 : public ast_matchers::internal::MatcherInterface<T> {
243 const DynTypedMatcher DescendantMatcher;
244
245public:
246 explicit DynamicForEachDescendantMatcher(DynTypedMatcher DescendantMatcher)
247 : DescendantMatcher(std::move(DescendantMatcher)) {}
248
249 bool matches(
250 const T &Node, ast_matchers::internal::ASTMatchFinder *Finder,
251 ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
252 return Finder->matchesDescendantOf(
253 Node, this->DescendantMatcher, Builder,
254 ast_matchers::internal::ASTMatchFinder::BK_All);
255 }
256};
257
258template <typename T>
259ast_matchers::internal::Matcher<T>
260forEachDescendantDynamically(ast_matchers::BoundNodes Nodes,
261 DynTypedMatcher M) {
262 return ast_matchers::internal::makeMatcher(new BindingsMatcher<T>(
263 std::move(Nodes),
264 ast_matchers::internal::makeMatcher(
265 new DynamicForEachDescendantMatcher<T>(std::move(M)))));
266}
267
268class ApplyRuleCallback : public MatchFinder::MatchCallback {
269public:
270 ApplyRuleCallback(RewriteRule Rule) : Rule(std::move(Rule)) {}
271
272 template <typename T>
273 void registerMatchers(const ast_matchers::BoundNodes &Nodes,
274 MatchFinder *MF) {
275 for (auto &Matcher : transformer::detail::buildMatchers(Rule))
276 MF->addMatcher(forEachDescendantDynamically<T>(Nodes, Matcher), this);
277 }
278
279 void run(const MatchFinder::MatchResult &Result) override {
280 if (!Edits)
281 return;
282 size_t I = transformer::detail::findSelectedCase(Result, Rule);
283 auto Transformations = Rule.Cases[I].Edits(Result);
284 if (!Transformations) {
285 Edits = Transformations.takeError();
286 return;
287 }
288 Edits->append(Transformations->begin(), Transformations->end());
289 }
290
291 RewriteRule Rule;
292
293 // Initialize to a non-error state.
294 Expected<SmallVector<Edit, 1>> Edits = SmallVector<Edit, 1>();
295};
296} // namespace
297
298template <typename T>
299llvm::Expected<SmallVector<clang::transformer::Edit, 1>>
300rewriteDescendantsImpl(const T &Node, RewriteRule Rule,
301 const MatchResult &Result) {
302 ApplyRuleCallback Callback(std::move(Rule));
303 MatchFinder Finder;
304 Callback.registerMatchers<T>(Result.Nodes, &Finder);
305 Finder.match(Node, *Result.Context);
306 return std::move(Callback.Edits);
307}
308
309llvm::Expected<SmallVector<clang::transformer::Edit, 1>>
310transformer::detail::rewriteDescendants(const Decl &Node, RewriteRule Rule,
311 const MatchResult &Result) {
312 return rewriteDescendantsImpl(Node, std::move(Rule), Result);
313}
314
315llvm::Expected<SmallVector<clang::transformer::Edit, 1>>
316transformer::detail::rewriteDescendants(const Stmt &Node, RewriteRule Rule,
317 const MatchResult &Result) {
318 return rewriteDescendantsImpl(Node, std::move(Rule), Result);
319}
320
321llvm::Expected<SmallVector<clang::transformer::Edit, 1>>
322transformer::detail::rewriteDescendants(const TypeLoc &Node, RewriteRule Rule,
323 const MatchResult &Result) {
324 return rewriteDescendantsImpl(Node, std::move(Rule), Result);
325}
326
327llvm::Expected<SmallVector<clang::transformer::Edit, 1>>
328transformer::detail::rewriteDescendants(const DynTypedNode &DNode,
329 RewriteRule Rule,
330 const MatchResult &Result) {
331 if (const auto *Node = DNode.get<Decl>())
332 return rewriteDescendantsImpl(*Node, std::move(Rule), Result);
333 if (const auto *Node = DNode.get<Stmt>())
334 return rewriteDescendantsImpl(*Node, std::move(Rule), Result);
335 if (const auto *Node = DNode.get<TypeLoc>())
336 return rewriteDescendantsImpl(*Node, std::move(Rule), Result);
337
338 return llvm::make_error<llvm::StringError>(
339 llvm::errc::invalid_argument,
340 "type unsupported for recursive rewriting, Kind=" +
341 DNode.getNodeKind().asStringRef());
342}
343
344EditGenerator transformer::rewriteDescendants(std::string NodeId,
345 RewriteRule Rule) {
346 return [NodeId = std::move(NodeId),
347 Rule = std::move(Rule)](const MatchResult &Result)
348 -> llvm::Expected<SmallVector<clang::transformer::Edit, 1>> {
349 const ast_matchers::BoundNodes::IDToNodeMap &NodesMap =
350 Result.Nodes.getMap();
351 auto It = NodesMap.find(NodeId);
352 if (It == NodesMap.end())
353 return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
354 "ID not bound: " + NodeId);
355 return detail::rewriteDescendants(It->second, std::move(Rule), Result);
356 };
357}
358
359void transformer::addInclude(RewriteRuleBase &Rule, StringRef Header,
360 IncludeFormat Format) {
361 for (auto &Case : Rule.Cases)
1
Assuming '__begin1' is not equal to '__end1'
362 Case.Edits = flatten(std::move(Case.Edits), addInclude(Header, Format));
2
Calling 'flatten<std::function<llvm::Expected<llvm::SmallVector<clang::transformer::Edit, 1>> (const clang::ast_matchers::MatchFinder::MatchResult &)>, clang::transformer::ASTEdit>'
363}
364
365#ifndef NDEBUG
366// Filters for supported matcher kinds. FIXME: Explicitly list the allowed kinds
367// (all node matcher types except for `QualType` and `Type`), rather than just
368// banning `QualType` and `Type`.
369static bool hasValidKind(const DynTypedMatcher &M) {
370 return !M.canConvertTo<QualType>();
371}
372#endif
373
374// Binds each rule's matcher to a unique (and deterministic) tag based on
375// `TagBase` and the id paired with the case. All of the returned matchers have
376// their traversal kind explicitly set, either based on a pre-set kind or to the
377// provided `DefaultTraversalKind`.
378static std::vector<DynTypedMatcher> taggedMatchers(
379 StringRef TagBase,
380 const SmallVectorImpl<std::pair<size_t, RewriteRule::Case>> &Cases,
381 TraversalKind DefaultTraversalKind) {
382 std::vector<DynTypedMatcher> Matchers;
383 Matchers.reserve(Cases.size());
384 for (const auto &Case : Cases) {
385 std::string Tag = (TagBase + Twine(Case.first)).str();
386 // HACK: Many matchers are not bindable, so ensure that tryBind will work.
387 DynTypedMatcher BoundMatcher(Case.second.Matcher);
388 BoundMatcher.setAllowBind(true);
389 auto M = *BoundMatcher.tryBind(Tag);
390 Matchers.push_back(!M.getTraversalKind()
391 ? M.withTraversalKind(DefaultTraversalKind)
392 : std::move(M));
393 }
394 return Matchers;
395}
396
397// Simply gathers the contents of the various rules into a single rule. The
398// actual work to combine these into an ordered choice is deferred to matcher
399// registration.
400template <>
401RewriteRuleWith<void>
402transformer::applyFirst(ArrayRef<RewriteRuleWith<void>> Rules) {
403 RewriteRule R;
404 for (auto &Rule : Rules)
405 R.Cases.append(Rule.Cases.begin(), Rule.Cases.end());
406 return R;
407}
408
409std::vector<DynTypedMatcher>
410transformer::detail::buildMatchers(const RewriteRuleBase &Rule) {
411 // Map the cases into buckets of matchers -- one for each "root" AST kind,
412 // which guarantees that they can be combined in a single anyOf matcher. Each
413 // case is paired with an identifying number that is converted to a string id
414 // in `taggedMatchers`.
415 std::map<ASTNodeKind,
416 SmallVector<std::pair<size_t, RewriteRuleBase::Case>, 1>>
417 Buckets;
418 const SmallVectorImpl<RewriteRule::Case> &Cases = Rule.Cases;
419 for (int I = 0, N = Cases.size(); I < N; ++I) {
420 assert(hasValidKind(Cases[I].Matcher) &&(static_cast <bool> (hasValidKind(Cases[I].Matcher) &&
"Matcher must be non-(Qual)Type node matcher") ? void (0) : __assert_fail
("hasValidKind(Cases[I].Matcher) && \"Matcher must be non-(Qual)Type node matcher\""
, "clang/lib/Tooling/Transformer/RewriteRule.cpp", 421, __extension__
__PRETTY_FUNCTION__))
421 "Matcher must be non-(Qual)Type node matcher")(static_cast <bool> (hasValidKind(Cases[I].Matcher) &&
"Matcher must be non-(Qual)Type node matcher") ? void (0) : __assert_fail
("hasValidKind(Cases[I].Matcher) && \"Matcher must be non-(Qual)Type node matcher\""
, "clang/lib/Tooling/Transformer/RewriteRule.cpp", 421, __extension__
__PRETTY_FUNCTION__))
;
422 Buckets[Cases[I].Matcher.getSupportedKind()].emplace_back(I, Cases[I]);
423 }
424
425 // Each anyOf explicitly controls the traversal kind. The anyOf itself is set
426 // to `TK_AsIs` to ensure no nodes are skipped, thereby deferring to the kind
427 // of the branches. Then, each branch is either left as is, if the kind is
428 // already set, or explicitly set to `TK_AsIs`. We choose this setting because
429 // it is the default interpretation of matchers.
430 std::vector<DynTypedMatcher> Matchers;
431 for (const auto &Bucket : Buckets) {
432 DynTypedMatcher M = DynTypedMatcher::constructVariadic(
433 DynTypedMatcher::VO_AnyOf, Bucket.first,
434 taggedMatchers("Tag", Bucket.second, TK_AsIs));
435 M.setAllowBind(true);
436 // `tryBind` is guaranteed to succeed, because `AllowBind` was set to true.
437 Matchers.push_back(M.tryBind(RootID)->withTraversalKind(TK_AsIs));
438 }
439 return Matchers;
440}
441
442DynTypedMatcher transformer::detail::buildMatcher(const RewriteRuleBase &Rule) {
443 std::vector<DynTypedMatcher> Ms = buildMatchers(Rule);
444 assert(Ms.size() == 1 && "Cases must have compatible matchers.")(static_cast <bool> (Ms.size() == 1 && "Cases must have compatible matchers."
) ? void (0) : __assert_fail ("Ms.size() == 1 && \"Cases must have compatible matchers.\""
, "clang/lib/Tooling/Transformer/RewriteRule.cpp", 444, __extension__
__PRETTY_FUNCTION__))
;
445 return Ms[0];
446}
447
448SourceLocation transformer::detail::getRuleMatchLoc(const MatchResult &Result) {
449 auto &NodesMap = Result.Nodes.getMap();
450 auto Root = NodesMap.find(RootID);
451 assert(Root != NodesMap.end() && "Transformation failed: missing root node.")(static_cast <bool> (Root != NodesMap.end() && "Transformation failed: missing root node."
) ? void (0) : __assert_fail ("Root != NodesMap.end() && \"Transformation failed: missing root node.\""
, "clang/lib/Tooling/Transformer/RewriteRule.cpp", 451, __extension__
__PRETTY_FUNCTION__))
;
452 std::optional<CharSourceRange> RootRange = tooling::getFileRangeForEdit(
453 CharSourceRange::getTokenRange(Root->second.getSourceRange()),
454 *Result.Context);
455 if (RootRange)
456 return RootRange->getBegin();
457 // The match doesn't have a coherent range, so fall back to the expansion
458 // location as the "beginning" of the match.
459 return Result.SourceManager->getExpansionLoc(
460 Root->second.getSourceRange().getBegin());
461}
462
463// Finds the case that was "selected" -- that is, whose matcher triggered the
464// `MatchResult`.
465size_t transformer::detail::findSelectedCase(const MatchResult &Result,
466 const RewriteRuleBase &Rule) {
467 if (Rule.Cases.size() == 1)
468 return 0;
469
470 auto &NodesMap = Result.Nodes.getMap();
471 for (size_t i = 0, N = Rule.Cases.size(); i < N; ++i) {
472 std::string Tag = ("Tag" + Twine(i)).str();
473 if (NodesMap.find(Tag) != NodesMap.end())
474 return i;
475 }
476 llvm_unreachable("No tag found for this rule.")::llvm::llvm_unreachable_internal("No tag found for this rule."
, "clang/lib/Tooling/Transformer/RewriteRule.cpp", 476)
;
477}

/build/source/clang/include/clang/Tooling/Transformer/RewriteRule.h

1//===--- RewriteRule.h - RewriteRule class ----------------------*- 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/// \file
10/// Defines the RewriteRule class and related functions for creating,
11/// modifying and interpreting RewriteRules.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_REWRITERULE_H
16#define LLVM_CLANG_TOOLING_TRANSFORMER_REWRITERULE_H
17
18#include "clang/ASTMatchers/ASTMatchFinder.h"
19#include "clang/ASTMatchers/ASTMatchers.h"
20#include "clang/ASTMatchers/ASTMatchersInternal.h"
21#include "clang/Tooling/Refactoring/AtomicChange.h"
22#include "clang/Tooling/Transformer/MatchConsumer.h"
23#include "clang/Tooling/Transformer/RangeSelector.h"
24#include "llvm/ADT/Any.h"
25#include "llvm/ADT/STLExtras.h"
26#include "llvm/ADT/SmallVector.h"
27#include "llvm/Support/Error.h"
28#include <functional>
29#include <string>
30#include <utility>
31
32namespace clang {
33namespace transformer {
34// Specifies how to interpret an edit.
35enum class EditKind {
36 // Edits a source range in the file.
37 Range,
38 // Inserts an include in the file. The `Replacement` field is the name of the
39 // newly included file.
40 AddInclude,
41};
42
43/// A concrete description of a source edit, represented by a character range in
44/// the source to be replaced and a corresponding replacement string.
45struct Edit {
46 EditKind Kind = EditKind::Range;
47 CharSourceRange Range;
48 std::string Replacement;
49 std::string Note;
50 llvm::Any Metadata;
51};
52
53/// Format of the path in an include directive -- angle brackets or quotes.
54enum class IncludeFormat {
55 Quoted,
56 Angled,
57};
58
59/// Maps a match result to a list of concrete edits (with possible
60/// failure). This type is a building block of rewrite rules, but users will
61/// generally work in terms of `ASTEdit`s (below) rather than directly in terms
62/// of `EditGenerator`.
63using EditGenerator = MatchConsumer<llvm::SmallVector<Edit, 1>>;
64
65template <typename T> using Generator = std::shared_ptr<MatchComputation<T>>;
66
67using TextGenerator = Generator<std::string>;
68
69using AnyGenerator = MatchConsumer<llvm::Any>;
70
71// Description of a source-code edit, expressed in terms of an AST node.
72// Includes: an ID for the (bound) node, a selector for source related to the
73// node, a replacement and, optionally, an explanation for the edit.
74//
75// * Target: the source code impacted by the rule. This identifies an AST node,
76// or part thereof (\c Part), whose source range indicates the extent of the
77// replacement applied by the replacement term. By default, the extent is the
78// node matched by the pattern term (\c NodePart::Node). Target's are typed
79// (\c Kind), which guides the determination of the node extent.
80//
81// * Replacement: a function that produces a replacement string for the target,
82// based on the match result.
83//
84// * Note: (optional) a note specifically for this edit, potentially referencing
85// elements of the match. This will be displayed to the user, where possible;
86// for example, in clang-tidy diagnostics. Use of notes should be rare --
87// explanations of the entire rewrite should be set in the rule
88// (`RewriteRule::Explanation`) instead. Notes serve the rare cases wherein
89// edit-specific diagnostics are required.
90//
91// `ASTEdit` should be built using the `change` convenience functions. For
92// example,
93// \code
94// changeTo(name(fun), cat("Frodo"))
95// \endcode
96// Or, if we use Stencil for the TextGenerator:
97// \code
98// using stencil::cat;
99// changeTo(statement(thenNode), cat("{", thenNode, "}"))
100// changeTo(callArgs(call), cat(x, ",", y))
101// \endcode
102// Or, if you are changing the node corresponding to the rule's matcher, you can
103// use the single-argument override of \c change:
104// \code
105// changeTo(cat("different_expr"))
106// \endcode
107struct ASTEdit {
108 EditKind Kind = EditKind::Range;
109 RangeSelector TargetRange;
110 TextGenerator Replacement;
111 TextGenerator Note;
112 // Not all transformations will want or need to attach metadata and therefore
113 // should not be required to do so.
114 AnyGenerator Metadata = [](const ast_matchers::MatchFinder::MatchResult &)
115 -> llvm::Expected<llvm::Any> {
116 return llvm::Expected<llvm::Any>(llvm::Any());
117 };
118};
119
120/// Generates a single (specified) edit.
121EditGenerator edit(ASTEdit E);
122
123/// Lifts a list of `ASTEdit`s into an `EditGenerator`.
124///
125/// The `EditGenerator` will return an empty vector if any of the edits apply to
126/// portions of the source that are ineligible for rewriting (certain
127/// interactions with macros, for example) and it will fail if any invariants
128/// are violated relating to bound nodes in the match. However, it does not
129/// fail in the case of conflicting edits -- conflict handling is left to
130/// clients. We recommend use of the \c AtomicChange or \c Replacements classes
131/// for assistance in detecting such conflicts.
132EditGenerator editList(llvm::SmallVector<ASTEdit, 1> Edits);
133
134/// Generates no edits.
135inline EditGenerator noEdits() { return editList({}); }
136
137/// Generates a single, no-op edit anchored at the start location of the
138/// specified range. A `noopEdit` may be preferred over `noEdits` to associate a
139/// diagnostic `Explanation` with the rule.
140EditGenerator noopEdit(RangeSelector Anchor);
141
142/// Generates a single, no-op edit with the associated note anchored at the
143/// start location of the specified range.
144ASTEdit note(RangeSelector Anchor, TextGenerator Note);
145
146/// Version of `ifBound` specialized to `ASTEdit`.
147inline EditGenerator ifBound(std::string ID, ASTEdit TrueEdit,
148 ASTEdit FalseEdit) {
149 return ifBound(std::move(ID), edit(std::move(TrueEdit)),
150 edit(std::move(FalseEdit)));
151}
152
153/// Version of `ifBound` that has no "False" branch. If the node is not bound,
154/// then no edits are produced.
155inline EditGenerator ifBound(std::string ID, ASTEdit TrueEdit) {
156 return ifBound(std::move(ID), edit(std::move(TrueEdit)), noEdits());
157}
158
159/// Flattens a list of generators into a single generator whose elements are the
160/// concatenation of the results of the argument generators.
161EditGenerator flattenVector(SmallVector<EditGenerator, 2> Generators);
162
163namespace detail {
164/// Helper function to construct an \c EditGenerator. Overloaded for common
165/// cases so that user doesn't need to specify which factory function to
166/// use. This pattern gives benefits similar to implicit constructors, while
167/// maintaing a higher degree of explicitness.
168inline EditGenerator injectEdits(ASTEdit E) { return edit(std::move(E)); }
4
Calling 'edit'
13
Returned allocated memory
169inline EditGenerator injectEdits(EditGenerator G) { return G; }
170} // namespace detail
171
172template <typename... Ts> EditGenerator flatten(Ts &&...Edits) {
173 return flattenVector({detail::injectEdits(std::forward<Ts>(Edits))...});
3
Calling 'injectEdits'
14
Returned allocated memory
174}
15
Potential memory leak
175
176// Every rewrite rule is triggered by a match against some AST node.
177// Transformer guarantees that this ID is bound to the triggering node whenever
178// a rewrite rule is applied.
179extern const char RootID[];
180
181/// Replaces a portion of the source text with \p Replacement.
182ASTEdit changeTo(RangeSelector Target, TextGenerator Replacement);
183/// DEPRECATED: use \c changeTo.
184inline ASTEdit change(RangeSelector Target, TextGenerator Replacement) {
185 return changeTo(std::move(Target), std::move(Replacement));
186}
187
188/// Replaces the entirety of a RewriteRule's match with \p Replacement. For
189/// example, to replace a function call, one could write:
190/// \code
191/// makeRule(callExpr(callee(functionDecl(hasName("foo")))),
192/// changeTo(cat("bar()")))
193/// \endcode
194inline ASTEdit changeTo(TextGenerator Replacement) {
195 return changeTo(node(RootID), std::move(Replacement));
196}
197/// DEPRECATED: use \c changeTo.
198inline ASTEdit change(TextGenerator Replacement) {
199 return changeTo(std::move(Replacement));
200}
201
202/// Inserts \p Replacement before \p S, leaving the source selected by \S
203/// unchanged.
204inline ASTEdit insertBefore(RangeSelector S, TextGenerator Replacement) {
205 return changeTo(before(std::move(S)), std::move(Replacement));
206}
207
208/// Inserts \p Replacement after \p S, leaving the source selected by \S
209/// unchanged.
210inline ASTEdit insertAfter(RangeSelector S, TextGenerator Replacement) {
211 return changeTo(after(std::move(S)), std::move(Replacement));
212}
213
214/// Removes the source selected by \p S.
215ASTEdit remove(RangeSelector S);
216
217/// Adds an include directive for the given header to the file of `Target`. The
218/// particular location specified by `Target` is ignored.
219ASTEdit addInclude(RangeSelector Target, StringRef Header,
220 IncludeFormat Format = IncludeFormat::Quoted);
221
222/// Adds an include directive for the given header to the file associated with
223/// `RootID`. If `RootID` matches inside a macro expansion, will add the
224/// directive to the file in which the macro was expanded (as opposed to the
225/// file in which the macro is defined).
226inline ASTEdit addInclude(StringRef Header,
227 IncludeFormat Format = IncludeFormat::Quoted) {
228 return addInclude(expansion(node(RootID)), Header, Format);
229}
230
231// FIXME: If `Metadata` returns an `llvm::Expected<T>` the `AnyGenerator` will
232// construct an `llvm::Expected<llvm::Any>` where no error is present but the
233// `llvm::Any` holds the error. This is unlikely but potentially surprising.
234// Perhaps the `llvm::Expected` should be unwrapped, or perhaps this should be a
235// compile-time error. No solution here is perfect.
236//
237// Note: This function template accepts any type callable with a MatchResult
238// rather than a `std::function` because the return-type needs to be deduced. If
239// it accepted a `std::function<R(MatchResult)>`, lambdas or other callable
240// types would not be able to deduce `R`, and users would be forced to specify
241// explicitly the type they intended to return by wrapping the lambda at the
242// call-site.
243template <typename Callable>
244inline ASTEdit withMetadata(ASTEdit Edit, Callable Metadata) {
245 Edit.Metadata =
246 [Gen = std::move(Metadata)](
247 const ast_matchers::MatchFinder::MatchResult &R) -> llvm::Any {
248 return Gen(R);
249 };
250
251 return Edit;
252}
253
254/// Assuming that the inner range is enclosed by the outer range, creates
255/// precision edits to remove the parts of the outer range that are not included
256/// in the inner range.
257inline EditGenerator shrinkTo(RangeSelector outer, RangeSelector inner) {
258 return editList({remove(enclose(before(outer), before(inner))),
259 remove(enclose(after(inner), after(outer)))});
260}
261
262/// Description of a source-code transformation.
263//
264// A *rewrite rule* describes a transformation of source code. A simple rule
265// contains each of the following components:
266//
267// * Matcher: the pattern term, expressed as clang matchers (with Transformer
268// extensions).
269//
270// * Edits: a set of Edits to the source code, described with ASTEdits.
271//
272// However, rules can also consist of (sub)rules, where the first that matches
273// is applied and the rest are ignored. So, the above components together form
274// a logical "case" and a rule is a sequence of cases.
275//
276// Rule cases have an additional, implicit, component: the parameters. These are
277// portions of the pattern which are left unspecified, yet bound in the pattern
278// so that we can reference them in the edits.
279//
280// The \c Transformer class can be used to apply the rewrite rule and obtain the
281// corresponding replacements.
282struct RewriteRuleBase {
283 struct Case {
284 ast_matchers::internal::DynTypedMatcher Matcher;
285 EditGenerator Edits;
286 };
287 // We expect RewriteRules will most commonly include only one case.
288 SmallVector<Case, 1> Cases;
289};
290
291/// A source-code transformation with accompanying metadata.
292///
293/// When a case of the rule matches, the \c Transformer invokes the
294/// corresponding metadata generator and provides it alongside the edits.
295template <typename MetadataT> struct RewriteRuleWith : RewriteRuleBase {
296 SmallVector<Generator<MetadataT>, 1> Metadata;
297};
298
299template <> struct RewriteRuleWith<void> : RewriteRuleBase {};
300
301using RewriteRule = RewriteRuleWith<void>;
302
303namespace detail {
304
305RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M,
306 EditGenerator Edits);
307
308template <typename MetadataT>
309RewriteRuleWith<MetadataT> makeRule(ast_matchers::internal::DynTypedMatcher M,
310 EditGenerator Edits,
311 Generator<MetadataT> Metadata) {
312 RewriteRuleWith<MetadataT> R;
313 R.Cases = {{std::move(M), std::move(Edits)}};
314 R.Metadata = {std::move(Metadata)};
315 return R;
316}
317
318inline EditGenerator makeEditGenerator(EditGenerator Edits) { return Edits; }
319EditGenerator makeEditGenerator(llvm::SmallVector<ASTEdit, 1> Edits);
320EditGenerator makeEditGenerator(ASTEdit Edit);
321
322} // namespace detail
323
324/// Constructs a simple \c RewriteRule. \c Edits can be an \c EditGenerator,
325/// multiple \c ASTEdits, or a single \c ASTEdit.
326/// @{
327template <int &..., typename EditsT>
328RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M,
329 EditsT &&Edits) {
330 return detail::makeRule(
331 std::move(M), detail::makeEditGenerator(std::forward<EditsT>(Edits)));
332}
333
334RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M,
335 std::initializer_list<ASTEdit> Edits);
336/// @}
337
338/// Overloads of \c makeRule that also generate metadata when matching.
339/// @{
340template <typename MetadataT, int &..., typename EditsT>
341RewriteRuleWith<MetadataT> makeRule(ast_matchers::internal::DynTypedMatcher M,
342 EditsT &&Edits,
343 Generator<MetadataT> Metadata) {
344 return detail::makeRule(
345 std::move(M), detail::makeEditGenerator(std::forward<EditsT>(Edits)),
346 std::move(Metadata));
347}
348
349template <typename MetadataT>
350RewriteRuleWith<MetadataT> makeRule(ast_matchers::internal::DynTypedMatcher M,
351 std::initializer_list<ASTEdit> Edits,
352 Generator<MetadataT> Metadata) {
353 return detail::makeRule(std::move(M),
354 detail::makeEditGenerator(std::move(Edits)),
355 std::move(Metadata));
356}
357/// @}
358
359/// For every case in Rule, adds an include directive for the given header. The
360/// common use is assumed to be a rule with only one case. For example, to
361/// replace a function call and add headers corresponding to the new code, one
362/// could write:
363/// \code
364/// auto R = makeRule(callExpr(callee(functionDecl(hasName("foo")))),
365/// changeTo(cat("bar()")));
366/// addInclude(R, "path/to/bar_header.h");
367/// addInclude(R, "vector", IncludeFormat::Angled);
368/// \endcode
369void addInclude(RewriteRuleBase &Rule, llvm::StringRef Header,
370 IncludeFormat Format = IncludeFormat::Quoted);
371
372/// Applies the first rule whose pattern matches; other rules are ignored. If
373/// the matchers are independent then order doesn't matter. In that case,
374/// `applyFirst` is simply joining the set of rules into one.
375//
376// `applyFirst` is like an `anyOf` matcher with an edit action attached to each
377// of its cases. Anywhere you'd use `anyOf(m1.bind("id1"), m2.bind("id2"))` and
378// then dispatch on those ids in your code for control flow, `applyFirst` lifts
379// that behavior to the rule level. So, you can write `applyFirst({makeRule(m1,
380// action1), makeRule(m2, action2), ...});`
381//
382// For example, consider a type `T` with a deterministic serialization function,
383// `serialize()`. For performance reasons, we would like to make it
384// non-deterministic. Therefore, we want to drop the expectation that
385// `a.serialize() = b.serialize() iff a = b` (although we'll maintain
386// `deserialize(a.serialize()) = a`).
387//
388// We have three cases to consider (for some equality function, `eq`):
389// ```
390// eq(a.serialize(), b.serialize()) --> eq(a,b)
391// eq(a, b.serialize()) --> eq(deserialize(a), b)
392// eq(a.serialize(), b) --> eq(a, deserialize(b))
393// ```
394//
395// `applyFirst` allows us to specify each independently:
396// ```
397// auto eq_fun = functionDecl(...);
398// auto method_call = cxxMemberCallExpr(...);
399//
400// auto two_calls = callExpr(callee(eq_fun), hasArgument(0, method_call),
401// hasArgument(1, method_call));
402// auto left_call =
403// callExpr(callee(eq_fun), callExpr(hasArgument(0, method_call)));
404// auto right_call =
405// callExpr(callee(eq_fun), callExpr(hasArgument(1, method_call)));
406//
407// RewriteRule R = applyFirst({makeRule(two_calls, two_calls_action),
408// makeRule(left_call, left_call_action),
409// makeRule(right_call, right_call_action)});
410// ```
411/// @{
412template <typename MetadataT>
413RewriteRuleWith<MetadataT>
414applyFirst(ArrayRef<RewriteRuleWith<MetadataT>> Rules) {
415 RewriteRuleWith<MetadataT> R;
416 for (auto &Rule : Rules) {
417 assert(Rule.Cases.size() == Rule.Metadata.size() &&(static_cast <bool> (Rule.Cases.size() == Rule.Metadata
.size() && "mis-match in case and metadata array size"
) ? void (0) : __assert_fail ("Rule.Cases.size() == Rule.Metadata.size() && \"mis-match in case and metadata array size\""
, "clang/include/clang/Tooling/Transformer/RewriteRule.h", 418
, __extension__ __PRETTY_FUNCTION__))
418 "mis-match in case and metadata array size")(static_cast <bool> (Rule.Cases.size() == Rule.Metadata
.size() && "mis-match in case and metadata array size"
) ? void (0) : __assert_fail ("Rule.Cases.size() == Rule.Metadata.size() && \"mis-match in case and metadata array size\""
, "clang/include/clang/Tooling/Transformer/RewriteRule.h", 418
, __extension__ __PRETTY_FUNCTION__))
;
419 R.Cases.append(Rule.Cases.begin(), Rule.Cases.end());
420 R.Metadata.append(Rule.Metadata.begin(), Rule.Metadata.end());
421 }
422 return R;
423}
424
425template <>
426RewriteRuleWith<void> applyFirst(ArrayRef<RewriteRuleWith<void>> Rules);
427
428template <typename MetadataT>
429RewriteRuleWith<MetadataT>
430applyFirst(const std::vector<RewriteRuleWith<MetadataT>> &Rules) {
431 return applyFirst(llvm::ArrayRef(Rules));
432}
433
434template <typename MetadataT>
435RewriteRuleWith<MetadataT>
436applyFirst(std::initializer_list<RewriteRuleWith<MetadataT>> Rules) {
437 return applyFirst(llvm::ArrayRef(Rules.begin(), Rules.end()));
438}
439/// @}
440
441/// Converts a \c RewriteRuleWith<T> to a \c RewriteRule by stripping off the
442/// metadata generators.
443template <int &..., typename MetadataT>
444std::enable_if_t<!std::is_same<MetadataT, void>::value, RewriteRule>
445stripMetadata(RewriteRuleWith<MetadataT> Rule) {
446 RewriteRule R;
447 R.Cases = std::move(Rule.Cases);
448 return R;
449}
450
451/// Applies `Rule` to all descendants of the node bound to `NodeId`. `Rule` can
452/// refer to nodes bound by the calling rule. `Rule` is not applied to the node
453/// itself.
454///
455/// For example,
456/// ```
457/// auto InlineX =
458/// makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
459/// makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))).bind("f"),
460/// flatten(
461/// changeTo(name("f"), cat("newName")),
462/// rewriteDescendants("body", InlineX)));
463/// ```
464/// Here, we find the function `f`, change its name to `newName` and change all
465/// appearances of `x` in its body to `3`.
466EditGenerator rewriteDescendants(std::string NodeId, RewriteRule Rule);
467
468/// The following three functions are a low-level part of the RewriteRule
469/// API. We expose them for use in implementing the fixtures that interpret
470/// RewriteRule, like Transformer and TransfomerTidy, or for more advanced
471/// users.
472//
473// FIXME: These functions are really public, if advanced, elements of the
474// RewriteRule API. Recast them as such. Or, just declare these functions
475// public and well-supported and move them out of `detail`.
476namespace detail {
477/// The following overload set is a version of `rewriteDescendants` that
478/// operates directly on the AST, rather than generating a Transformer
479/// combinator. It applies `Rule` to all descendants of `Node`, although not
480/// `Node` itself. `Rule` can refer to nodes bound in `Result`.
481///
482/// For example, assuming that "body" is bound to a function body in MatchResult
483/// `Results`, this will produce edits to change all appearances of `x` in that
484/// body to `3`.
485/// ```
486/// auto InlineX =
487/// makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
488/// const auto *Node = Results.Nodes.getNodeAs<Stmt>("body");
489/// auto Edits = rewriteDescendants(*Node, InlineX, Results);
490/// ```
491/// @{
492llvm::Expected<SmallVector<Edit, 1>>
493rewriteDescendants(const Decl &Node, RewriteRule Rule,
494 const ast_matchers::MatchFinder::MatchResult &Result);
495
496llvm::Expected<SmallVector<Edit, 1>>
497rewriteDescendants(const Stmt &Node, RewriteRule Rule,
498 const ast_matchers::MatchFinder::MatchResult &Result);
499
500llvm::Expected<SmallVector<Edit, 1>>
501rewriteDescendants(const TypeLoc &Node, RewriteRule Rule,
502 const ast_matchers::MatchFinder::MatchResult &Result);
503
504llvm::Expected<SmallVector<Edit, 1>>
505rewriteDescendants(const DynTypedNode &Node, RewriteRule Rule,
506 const ast_matchers::MatchFinder::MatchResult &Result);
507/// @}
508
509/// Builds a single matcher for the rule, covering all of the rule's cases.
510/// Only supports Rules whose cases' matchers share the same base "kind"
511/// (`Stmt`, `Decl`, etc.) Deprecated: use `buildMatchers` instead, which
512/// supports mixing matchers of different kinds.
513ast_matchers::internal::DynTypedMatcher
514buildMatcher(const RewriteRuleBase &Rule);
515
516/// Builds a set of matchers that cover the rule.
517///
518/// One matcher is built for each distinct node matcher base kind: Stmt, Decl,
519/// etc. Node-matchers for `QualType` and `Type` are not permitted, since such
520/// nodes carry no source location information and are therefore not relevant
521/// for rewriting. If any such matchers are included, will return an empty
522/// vector.
523std::vector<ast_matchers::internal::DynTypedMatcher>
524buildMatchers(const RewriteRuleBase &Rule);
525
526/// Gets the beginning location of the source matched by a rewrite rule. If the
527/// match occurs within a macro expansion, returns the beginning of the
528/// expansion point. `Result` must come from the matching of a rewrite rule.
529SourceLocation
530getRuleMatchLoc(const ast_matchers::MatchFinder::MatchResult &Result);
531
532/// Returns the index of the \c Case of \c Rule that was selected in the match
533/// result. Assumes a matcher built with \c buildMatcher.
534size_t findSelectedCase(const ast_matchers::MatchFinder::MatchResult &Result,
535 const RewriteRuleBase &Rule);
536} // namespace detail
537} // namespace transformer
538} // namespace clang
539
540#endif // LLVM_CLANG_TOOLING_TRANSFORMER_REWRITERULE_H

/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h

1// Implementation of std::function -*- C++ -*-
2
3// Copyright (C) 2004-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file include/bits/std_function.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{functional}
28 */
29
30#ifndef _GLIBCXX_STD_FUNCTION_H1
31#define _GLIBCXX_STD_FUNCTION_H1 1
32
33#pragma GCC system_header
34
35#if __cplusplus201703L < 201103L
36# include <bits/c++0x_warning.h>
37#else
38
39#if __cpp_rtti199711L
40# include <typeinfo>
41#endif
42#include <bits/stl_function.h>
43#include <bits/invoke.h>
44#include <bits/refwrap.h>
45#include <bits/functexcept.h>
46
47namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
48{
49_GLIBCXX_BEGIN_NAMESPACE_VERSION
50
51 /**
52 * @brief Exception class thrown when class template function's
53 * operator() is called with an empty target.
54 * @ingroup exceptions
55 */
56 class bad_function_call : public std::exception
57 {
58 public:
59 virtual ~bad_function_call() noexcept;
60
61 const char* what() const noexcept;
62 };
63
64 /**
65 * Trait identifying "location-invariant" types, meaning that the
66 * address of the object (or any of its members) will not escape.
67 * Trivially copyable types are location-invariant and users can
68 * specialize this trait for other types.
69 */
70 template<typename _Tp>
71 struct __is_location_invariant
72 : is_trivially_copyable<_Tp>::type
73 { };
74
75 class _Undefined_class;
76
77 union _Nocopy_types
78 {
79 void* _M_object;
80 const void* _M_const_object;
81 void (*_M_function_pointer)();
82 void (_Undefined_class::*_M_member_pointer)();
83 };
84
85 union [[gnu::may_alias]] _Any_data
86 {
87 void* _M_access() { return &_M_pod_data[0]; }
88 const void* _M_access() const { return &_M_pod_data[0]; }
89
90 template<typename _Tp>
91 _Tp&
92 _M_access()
93 { return *static_cast<_Tp*>(_M_access()); }
94
95 template<typename _Tp>
96 const _Tp&
97 _M_access() const
98 { return *static_cast<const _Tp*>(_M_access()); }
99
100 _Nocopy_types _M_unused;
101 char _M_pod_data[sizeof(_Nocopy_types)];
102 };
103
104 enum _Manager_operation
105 {
106 __get_type_info,
107 __get_functor_ptr,
108 __clone_functor,
109 __destroy_functor
110 };
111
112 template<typename _Signature>
113 class function;
114
115 /// Base class of all polymorphic function object wrappers.
116 class _Function_base
117 {
118 public:
119 static const size_t _M_max_size = sizeof(_Nocopy_types);
120 static const size_t _M_max_align = __alignof__(_Nocopy_types);
121
122 template<typename _Functor>
123 class _Base_manager
124 {
125 protected:
126 static const bool __stored_locally =
127 (__is_location_invariant<_Functor>::value
128 && sizeof(_Functor) <= _M_max_size
129 && __alignof__(_Functor) <= _M_max_align
130 && (_M_max_align % __alignof__(_Functor) == 0));
131
132 typedef integral_constant<bool, __stored_locally> _Local_storage;
133
134 // Retrieve a pointer to the function object
135 static _Functor*
136 _M_get_pointer(const _Any_data& __source)
137 {
138 if _GLIBCXX17_CONSTEXPRconstexpr (__stored_locally)
139 {
140 const _Functor& __f = __source._M_access<_Functor>();
141 return const_cast<_Functor*>(std::__addressof(__f));
142 }
143 else // have stored a pointer
144 return __source._M_access<_Functor*>();
145 }
146
147 // Clone a location-invariant function object that fits within
148 // an _Any_data structure.
149 static void
150 _M_clone(_Any_data& __dest, const _Any_data& __source, true_type)
151 {
152 ::new (__dest._M_access()) _Functor(__source._M_access<_Functor>());
153 }
154
155 // Clone a function object that is not location-invariant or
156 // that cannot fit into an _Any_data structure.
157 static void
158 _M_clone(_Any_data& __dest, const _Any_data& __source, false_type)
159 {
160 __dest._M_access<_Functor*>() =
161 new _Functor(*__source._M_access<const _Functor*>());
162 }
163
164 // Destroying a location-invariant object may still require
165 // destruction.
166 static void
167 _M_destroy(_Any_data& __victim, true_type)
168 {
169 __victim._M_access<_Functor>().~_Functor();
170 }
171
172 // Destroying an object located on the heap.
173 static void
174 _M_destroy(_Any_data& __victim, false_type)
175 {
176 delete __victim._M_access<_Functor*>();
177 }
178
179 public:
180 static bool
181 _M_manager(_Any_data& __dest, const _Any_data& __source,
182 _Manager_operation __op)
183 {
184 switch (__op)
185 {
186#if __cpp_rtti199711L
187 case __get_type_info:
188 __dest._M_access<const type_info*>() = &typeid(_Functor);
189 break;
190#endif
191 case __get_functor_ptr:
192 __dest._M_access<_Functor*>() = _M_get_pointer(__source);
193 break;
194
195 case __clone_functor:
196 _M_clone(__dest, __source, _Local_storage());
197 break;
198
199 case __destroy_functor:
200 _M_destroy(__dest, _Local_storage());
201 break;
202 }
203 return false;
204 }
205
206 static void
207 _M_init_functor(_Any_data& __functor, _Functor&& __f)
208 { _M_init_functor(__functor, std::move(__f), _Local_storage()); }
8
Calling '_Base_manager::_M_init_functor'
10
Returned allocated memory
209
210 template<typename _Signature>
211 static bool
212 _M_not_empty_function(const function<_Signature>& __f)
213 { return static_cast<bool>(__f); }
214
215 template<typename _Tp>
216 static bool
217 _M_not_empty_function(_Tp* __fp)
218 { return __fp != nullptr; }
219
220 template<typename _Class, typename _Tp>
221 static bool
222 _M_not_empty_function(_Tp _Class::* __mp)
223 { return __mp != nullptr; }
224
225 template<typename _Tp>
226 static bool
227 _M_not_empty_function(const _Tp&)
228 { return true; }
229
230 private:
231 static void
232 _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type)
233 { ::new (__functor._M_access()) _Functor(std::move(__f)); }
234
235 static void
236 _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type)
237 { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
9
Memory is allocated
238 };
239
240 _Function_base() : _M_manager(nullptr) { }
241
242 ~_Function_base()
243 {
244 if (_M_manager)
245 _M_manager(_M_functor, _M_functor, __destroy_functor);
246 }
247
248 bool _M_empty() const { return !_M_manager; }
249
250 typedef bool (*_Manager_type)(_Any_data&, const _Any_data&,
251 _Manager_operation);
252
253 _Any_data _M_functor;
254 _Manager_type _M_manager;
255 };
256
257 template<typename _Signature, typename _Functor>
258 class _Function_handler;
259
260 template<typename _Res, typename _Functor, typename... _ArgTypes>
261 class _Function_handler<_Res(_ArgTypes...), _Functor>
262 : public _Function_base::_Base_manager<_Functor>
263 {
264 typedef _Function_base::_Base_manager<_Functor> _Base;
265
266 public:
267 static bool
268 _M_manager(_Any_data& __dest, const _Any_data& __source,
269 _Manager_operation __op)
270 {
271 switch (__op)
272 {
273#if __cpp_rtti199711L
274 case __get_type_info:
275 __dest._M_access<const type_info*>() = &typeid(_Functor);
276 break;
277#endif
278 case __get_functor_ptr:
279 __dest._M_access<_Functor*>() = _Base::_M_get_pointer(__source);
280 break;
281
282 default:
283 _Base::_M_manager(__dest, __source, __op);
284 }
285 return false;
286 }
287
288 static _Res
289 _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
290 {
291 return std::__invoke_r<_Res>(*_Base::_M_get_pointer(__functor),
292 std::forward<_ArgTypes>(__args)...);
293 }
294 };
295
296 /**
297 * @brief Primary class template for std::function.
298 * @ingroup functors
299 *
300 * Polymorphic function wrapper.
301 */
302 template<typename _Res, typename... _ArgTypes>
303 class function<_Res(_ArgTypes...)>
304 : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>,
305 private _Function_base
306 {
307 template<typename _Func,
308 typename _Res2 = __invoke_result<_Func&, _ArgTypes...>>
309 struct _Callable
310 : __is_invocable_impl<_Res2, _Res>::type
311 { };
312
313 // Used so the return type convertibility checks aren't done when
314 // performing overload resolution for copy construction/assignment.
315 template<typename _Tp>
316 struct _Callable<function, _Tp> : false_type { };
317
318 template<typename _Cond, typename _Tp>
319 using _Requires = typename enable_if<_Cond::value, _Tp>::type;
320
321 public:
322 typedef _Res result_type;
323
324 // [3.7.2.1] construct/copy/destroy
325
326 /**
327 * @brief Default construct creates an empty function call wrapper.
328 * @post @c !(bool)*this
329 */
330 function() noexcept
331 : _Function_base() { }
332
333 /**
334 * @brief Creates an empty function call wrapper.
335 * @post @c !(bool)*this
336 */
337 function(nullptr_t) noexcept
338 : _Function_base() { }
339
340 /**
341 * @brief %Function copy constructor.
342 * @param __x A %function object with identical call signature.
343 * @post @c bool(*this) == bool(__x)
344 *
345 * The newly-created %function contains a copy of the target of @a
346 * __x (if it has one).
347 */
348 function(const function& __x);
349
350 /**
351 * @brief %Function move constructor.
352 * @param __x A %function object rvalue with identical call signature.
353 *
354 * The newly-created %function contains the target of @a __x
355 * (if it has one).
356 */
357 function(function&& __x) noexcept : _Function_base()
358 {
359 __x.swap(*this);
360 }
361
362 /**
363 * @brief Builds a %function that targets a copy of the incoming
364 * function object.
365 * @param __f A %function object that is callable with parameters of
366 * type @c T1, @c T2, ..., @c TN and returns a value convertible
367 * to @c Res.
368 *
369 * The newly-created %function object will target a copy of
370 * @a __f. If @a __f is @c reference_wrapper<F>, then this function
371 * object will contain a reference to the function object @c
372 * __f.get(). If @a __f is a NULL function pointer or NULL
373 * pointer-to-member, the newly-created object will be empty.
374 *
375 * If @a __f is a non-NULL function pointer or an object of type @c
376 * reference_wrapper<F>, this function will not throw.
377 */
378 template<typename _Functor,
379 typename = _Requires<__not_<is_same<_Functor, function>>, void>,
380 typename = _Requires<_Callable<_Functor>, void>>
381 function(_Functor);
382
383 /**
384 * @brief %Function assignment operator.
385 * @param __x A %function with identical call signature.
386 * @post @c (bool)*this == (bool)x
387 * @returns @c *this
388 *
389 * The target of @a __x is copied to @c *this. If @a __x has no
390 * target, then @c *this will be empty.
391 *
392 * If @a __x targets a function pointer or a reference to a function
393 * object, then this operation will not throw an %exception.
394 */
395 function&
396 operator=(const function& __x)
397 {
398 function(__x).swap(*this);
399 return *this;
400 }
401
402 /**
403 * @brief %Function move-assignment operator.
404 * @param __x A %function rvalue with identical call signature.
405 * @returns @c *this
406 *
407 * The target of @a __x is moved to @c *this. If @a __x has no
408 * target, then @c *this will be empty.
409 *
410 * If @a __x targets a function pointer or a reference to a function
411 * object, then this operation will not throw an %exception.
412 */
413 function&
414 operator=(function&& __x) noexcept
415 {
416 function(std::move(__x)).swap(*this);
417 return *this;
418 }
419
420 /**
421 * @brief %Function assignment to zero.
422 * @post @c !(bool)*this
423 * @returns @c *this
424 *
425 * The target of @c *this is deallocated, leaving it empty.
426 */
427 function&
428 operator=(nullptr_t) noexcept
429 {
430 if (_M_manager)
431 {
432 _M_manager(_M_functor, _M_functor, __destroy_functor);
433 _M_manager = nullptr;
434 _M_invoker = nullptr;
435 }
436 return *this;
437 }
438
439 /**
440 * @brief %Function assignment to a new target.
441 * @param __f A %function object that is callable with parameters of
442 * type @c T1, @c T2, ..., @c TN and returns a value convertible
443 * to @c Res.
444 * @return @c *this
445 *
446 * This %function object wrapper will target a copy of @a
447 * __f. If @a __f is @c reference_wrapper<F>, then this function
448 * object will contain a reference to the function object @c
449 * __f.get(). If @a __f is a NULL function pointer or NULL
450 * pointer-to-member, @c this object will be empty.
451 *
452 * If @a __f is a non-NULL function pointer or an object of type @c
453 * reference_wrapper<F>, this function will not throw.
454 */
455 template<typename _Functor>
456 _Requires<_Callable<typename decay<_Functor>::type>, function&>
457 operator=(_Functor&& __f)
458 {
459 function(std::forward<_Functor>(__f)).swap(*this);
460 return *this;
461 }
462
463 /// @overload
464 template<typename _Functor>
465 function&
466 operator=(reference_wrapper<_Functor> __f) noexcept
467 {
468 function(__f).swap(*this);
469 return *this;
470 }
471
472 // [3.7.2.2] function modifiers
473
474 /**
475 * @brief Swap the targets of two %function objects.
476 * @param __x A %function with identical call signature.
477 *
478 * Swap the targets of @c this function object and @a __f. This
479 * function will not throw an %exception.
480 */
481 void swap(function& __x) noexcept
482 {
483 std::swap(_M_functor, __x._M_functor);
484 std::swap(_M_manager, __x._M_manager);
485 std::swap(_M_invoker, __x._M_invoker);
486 }
487
488 // [3.7.2.3] function capacity
489
490 /**
491 * @brief Determine if the %function wrapper has a target.
492 *
493 * @return @c true when this %function object contains a target,
494 * or @c false when it is empty.
495 *
496 * This function will not throw an %exception.
497 */
498 explicit operator bool() const noexcept
499 { return !_M_empty(); }
500
501 // [3.7.2.4] function invocation
502
503 /**
504 * @brief Invokes the function targeted by @c *this.
505 * @returns the result of the target.
506 * @throws bad_function_call when @c !(bool)*this
507 *
508 * The function call operator invokes the target function object
509 * stored by @c this.
510 */
511 _Res operator()(_ArgTypes... __args) const;
512
513#if __cpp_rtti199711L
514 // [3.7.2.5] function target access
515 /**
516 * @brief Determine the type of the target of this function object
517 * wrapper.
518 *
519 * @returns the type identifier of the target function object, or
520 * @c typeid(void) if @c !(bool)*this.
521 *
522 * This function will not throw an %exception.
523 */
524 const type_info& target_type() const noexcept;
525
526 /**
527 * @brief Access the stored target function object.
528 *
529 * @return Returns a pointer to the stored target function object,
530 * if @c typeid(_Functor).equals(target_type()); otherwise, a NULL
531 * pointer.
532 *
533 * This function does not throw exceptions.
534 *
535 * @{
536 */
537 template<typename _Functor> _Functor* target() noexcept;
538
539 template<typename _Functor> const _Functor* target() const noexcept;
540 // @}
541#endif
542
543 private:
544 using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
545 _Invoker_type _M_invoker;
546 };
547
548#if __cpp_deduction_guides201703L >= 201606
549 template<typename>
550 struct __function_guide_helper
551 { };
552
553 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
554 struct __function_guide_helper<
555 _Res (_Tp::*) (_Args...) noexcept(_Nx)
556 >
557 { using type = _Res(_Args...); };
558
559 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
560 struct __function_guide_helper<
561 _Res (_Tp::*) (_Args...) & noexcept(_Nx)
562 >
563 { using type = _Res(_Args...); };
564
565 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
566 struct __function_guide_helper<
567 _Res (_Tp::*) (_Args...) const noexcept(_Nx)
568 >
569 { using type = _Res(_Args...); };
570
571 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
572 struct __function_guide_helper<
573 _Res (_Tp::*) (_Args...) const & noexcept(_Nx)
574 >
575 { using type = _Res(_Args...); };
576
577 template<typename _Res, typename... _ArgTypes>
578 function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>;
579
580 template<typename _Functor, typename _Signature = typename
581 __function_guide_helper<decltype(&_Functor::operator())>::type>
582 function(_Functor) -> function<_Signature>;
583#endif
584
585 // Out-of-line member definitions.
586 template<typename _Res, typename... _ArgTypes>
587 function<_Res(_ArgTypes...)>::
588 function(const function& __x)
589 : _Function_base()
590 {
591 if (static_cast<bool>(__x))
592 {
593 __x._M_manager(_M_functor, __x._M_functor, __clone_functor);
594 _M_invoker = __x._M_invoker;
595 _M_manager = __x._M_manager;
596 }
597 }
598
599 template<typename _Res, typename... _ArgTypes>
600 template<typename _Functor, typename, typename>
601 function<_Res(_ArgTypes...)>::
602 function(_Functor __f)
603 : _Function_base()
604 {
605 typedef _Function_handler<_Res(_ArgTypes...), _Functor> _My_handler;
606
607 if (_My_handler::_M_not_empty_function(__f))
6
Taking true branch
608 {
609 _My_handler::_M_init_functor(_M_functor, std::move(__f));
7
Calling '_Base_manager::_M_init_functor'
11
Returned allocated memory
610 _M_invoker = &_My_handler::_M_invoke;
611 _M_manager = &_My_handler::_M_manager;
612 }
613 }
614
615 template<typename _Res, typename... _ArgTypes>
616 _Res
617 function<_Res(_ArgTypes...)>::
618 operator()(_ArgTypes... __args) const
619 {
620 if (_M_empty())
621 __throw_bad_function_call();
622 return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
623 }
624
625#if __cpp_rtti199711L
626 template<typename _Res, typename... _ArgTypes>
627 const type_info&
628 function<_Res(_ArgTypes...)>::
629 target_type() const noexcept
630 {
631 if (_M_manager)
632 {
633 _Any_data __typeinfo_result;
634 _M_manager(__typeinfo_result, _M_functor, __get_type_info);
635 return *__typeinfo_result._M_access<const type_info*>();
636 }
637 else
638 return typeid(void);
639 }
640
641 template<typename _Res, typename... _ArgTypes>
642 template<typename _Functor>
643 _Functor*
644 function<_Res(_ArgTypes...)>::
645 target() noexcept
646 {
647 const function* __const_this = this;
648 const _Functor* __func = __const_this->template target<_Functor>();
649 return const_cast<_Functor*>(__func);
650 }
651
652 template<typename _Res, typename... _ArgTypes>
653 template<typename _Functor>
654 const _Functor*
655 function<_Res(_ArgTypes...)>::
656 target() const noexcept
657 {
658 if (typeid(_Functor) == target_type() && _M_manager)
659 {
660 _Any_data __ptr;
661 _M_manager(__ptr, _M_functor, __get_functor_ptr);
662 return __ptr._M_access<const _Functor*>();
663 }
664 else
665 return nullptr;
666 }
667#endif
668
669 // [20.7.15.2.6] null pointer comparisons
670
671 /**
672 * @brief Compares a polymorphic function object wrapper against 0
673 * (the NULL pointer).
674 * @returns @c true if the wrapper has no target, @c false otherwise
675 *
676 * This function will not throw an %exception.
677 */
678 template<typename _Res, typename... _Args>
679 inline bool
680 operator==(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
681 { return !static_cast<bool>(__f); }
682
683#if __cpp_impl_three_way_comparison < 201907L
684 /// @overload
685 template<typename _Res, typename... _Args>
686 inline bool
687 operator==(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
688 { return !static_cast<bool>(__f); }
689
690 /**
691 * @brief Compares a polymorphic function object wrapper against 0
692 * (the NULL pointer).
693 * @returns @c false if the wrapper has no target, @c true otherwise
694 *
695 * This function will not throw an %exception.
696 */
697 template<typename _Res, typename... _Args>
698 inline bool
699 operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
700 { return static_cast<bool>(__f); }
701
702 /// @overload
703 template<typename _Res, typename... _Args>
704 inline bool
705 operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
706 { return static_cast<bool>(__f); }
707#endif
708
709 // [20.7.15.2.7] specialized algorithms
710
711 /**
712 * @brief Swap the targets of two polymorphic function object wrappers.
713 *
714 * This function will not throw an %exception.
715 */
716 // _GLIBCXX_RESOLVE_LIB_DEFECTS
717 // 2062. Effect contradictions w/o no-throw guarantee of std::function swaps
718 template<typename _Res, typename... _Args>
719 inline void
720 swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept
721 { __x.swap(__y); }
722
723#if __cplusplus201703L >= 201703L
724 namespace __detail::__variant
725 {
726 template<typename> struct _Never_valueless_alt; // see <variant>
727
728 // Provide the strong exception-safety guarantee when emplacing a
729 // function into a variant.
730 template<typename _Signature>
731 struct _Never_valueless_alt<std::function<_Signature>>
732 : std::true_type
733 { };
734 } // namespace __detail::__variant
735#endif // C++17
736
737_GLIBCXX_END_NAMESPACE_VERSION
738} // namespace std
739
740#endif // C++11
741#endif // _GLIBCXX_STD_FUNCTION_H