diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-06-13 19:31:46 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-31 18:56:55 +0000 |
commit | af732203b8f7f006927528db5497f5cbc4c4742a (patch) | |
tree | 596f112de3b76118552871dbb6114bb7e3e17f40 /contrib/llvm-project/clang/include/clang/Tooling/Transformer | |
parent | 83dea422ac8d4a8323e64203c2eadaa813768717 (diff) | |
download | src-af732203b8f7f006927528db5497f5cbc4c4742a.tar.gz src-af732203b8f7f006927528db5497f5cbc4c4742a.zip |
Merge llvm-project 12.0.1 release and follow-up fixes
Merge llvm-project main llvmorg-12-init-17869-g8e464dd76bef
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-12-init-17869-g8e464dd76bef, the last commit before the
upstream release/12.x branch was created.
PR: 255570
(cherry picked from commit e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
Merge llvm-project 12.0.0 release
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-12.0.0-0-gd28af7c654d8, a.k.a. 12.0.0 release.
PR: 255570
(cherry picked from commit d409305fa3838fb39b38c26fc085fb729b8766d5)
Disable strict-fp for powerpcspe, as it does not work properly yet
Merge commit 5c18d1136665 from llvm git (by Qiu Chaofan)
[SPE] Disable strict-fp for SPE by default
As discussed in PR50385, strict-fp on PowerPC SPE has not been
handled well. This patch disables it by default for SPE.
Reviewed By: nemanjai, vit9696, jhibbits
Differential Revision: https://reviews.llvm.org/D103235
PR: 255570
(cherry picked from commit 715df83abc049b23d9acddc81f2480bd4c056d64)
Apply upstream libc++ fix to allow building with devel/xxx-xtoolchain-gcc
Merge commit 52e9d80d5db2 from llvm git (by Jason Liu):
[libc++] add `inline` for __open's definition in ifstream and ofstream
Summary:
When building with gcc on AIX, it seems that gcc does not like the
`always_inline` without the `inline` keyword.
So adding the inline keywords in for __open in ifstream and ofstream.
That will also make it consistent with __open in basic_filebuf
(it seems we added `inline` there before for gcc build as well).
Differential Revision: https://reviews.llvm.org/D99422
PR: 255570
(cherry picked from commit d099db25464b826c5724cf2fb5b22292bbe15f6e)
Undefine HAVE_(DE)REGISTER_FRAME in llvm's config.h on arm
Otherwise, the lli tool (enable by WITH_CLANG_EXTRAS) won't link on arm,
stating that __register_frame is undefined. This function is normally
provided by libunwind, but explicitly not for the ARM Exception ABI.
Reported by: oh
PR: 255570
(cherry picked from commit f336b45e943c7f9a90ffcea1a6c4c7039e54c73c)
Merge llvm-project 12.0.1 rc2
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-12.0.1-rc2-0-ge7dac564cd0e, a.k.a. 12.0.1 rc2.
PR: 255570
(cherry picked from commit 23408297fbf3089f0388a8873b02fa75ab3f5bb9)
Revert libunwind change to fix backtrace segfault on aarch64
Revert commit 22b615a96593 from llvm git (by Daniel Kiss):
[libunwind] Support for leaf function unwinding.
Unwinding leaf function is useful in cases when the backtrace finds a
leaf function for example when it caused a signal.
This patch also add the support for the DW_CFA_undefined because it marks
the end of the frames.
Ryan Prichard provided code for the tests.
Reviewed By: #libunwind, mstorsjo
Differential Revision: https://reviews.llvm.org/D83573
Reland with limit the test to the x86_64-linux target.
Bisection has shown that this particular upstream commit causes programs
using backtrace(3) on aarch64 to segfault. This affects the lang/rust
port, for instance. Until we can upstream to fix this problem, revert
the commit for now.
Reported by: mikael
PR: 256864
(cherry picked from commit 5866c369e4fd917c0d456f0f10b92ee354b82279)
Merge llvm-project 12.0.1 release
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-12.0.1-0-gfed41342a82f, a.k.a. 12.0.1 release.
PR: 255570
(cherry picked from commit 4652422eb477731f284b1345afeefef7f269da50)
compilert-rt: build out-of-line LSE atomics helpers for aarch64
Both clang >= 12 and gcc >= 10.1 now default to -moutline-atomics for
aarch64. This requires a bunch of helper functions in libcompiler_rt.a,
to avoid link errors like "undefined symbol: __aarch64_ldadd8_acq_rel".
(Note: of course you can use -mno-outline-atomics as a workaround too,
but this would negate the potential performance benefit of the faster
LSE instructions.)
Bump __FreeBSD_version so ports maintainers can easily detect this.
PR: 257392
(cherry picked from commit cc55ee8009a550810d38777fd6ace9abf3a2f6b4)
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/Tooling/Transformer')
4 files changed, 222 insertions, 114 deletions
diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Transformer/MatchConsumer.h b/contrib/llvm-project/clang/include/clang/Tooling/Transformer/MatchConsumer.h index f407ffce3d25..cb0a5f684b7d 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Transformer/MatchConsumer.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Transformer/MatchConsumer.h @@ -99,11 +99,5 @@ llvm::Expected<T> MatchComputation<T>::eval( return Output; } } // namespace transformer - -namespace tooling { -// DEPRECATED: Temporary alias supporting client migration to the `transformer` -// namespace. -using transformer::ifBound; -} // namespace tooling } // namespace clang #endif // LLVM_CLANG_TOOLING_TRANSFORMER_MATCH_CONSUMER_H_ diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Transformer/RangeSelector.h b/contrib/llvm-project/clang/include/clang/Tooling/Transformer/RangeSelector.h index 2807037bc208..f17fb8c7b5c6 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Transformer/RangeSelector.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Transformer/RangeSelector.h @@ -56,8 +56,13 @@ RangeSelector before(RangeSelector Selector); /// * the TokenRange [B,E'] where the token at E' spans the range [E',E). RangeSelector after(RangeSelector Selector); -/// Selects a node, including trailing semicolon (for non-expression -/// statements). \p ID is the node's binding in the match result. +/// Selects the range between `R1` and `R2. +inline RangeSelector between(RangeSelector R1, RangeSelector R2) { + return enclose(after(std::move(R1)), before(std::move(R2))); +} + +/// Selects a node, including trailing semicolon, if any (for declarations and +/// non-expression statements). \p ID is the node's binding in the match result. RangeSelector node(std::string ID); /// Selects a node, including trailing semicolon (always). Useful for selecting @@ -98,26 +103,6 @@ RangeSelector elseBranch(std::string ID); /// `SourceManager::getExpansionRange`. RangeSelector expansion(RangeSelector S); } // namespace transformer - -namespace tooling { -// DEPRECATED: These are temporary aliases supporting client migration to the -// `transformer` namespace. -using RangeSelector = transformer::RangeSelector; - -using transformer::after; -using transformer::before; -using transformer::callArgs; -using transformer::charRange; -using transformer::elseBranch; -using transformer::expansion; -using transformer::initListElements; -using transformer::member; -using transformer::name; -using transformer::node; -using transformer::range; -using transformer::statement; -using transformer::statements; -} // namespace tooling } // namespace clang #endif // LLVM_CLANG_TOOLING_REFACTOR_RANGE_SELECTOR_H_ diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Transformer/RewriteRule.h b/contrib/llvm-project/clang/include/clang/Tooling/Transformer/RewriteRule.h index d9e68717d5c8..ac93db8446df 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Transformer/RewriteRule.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Transformer/RewriteRule.h @@ -31,14 +31,30 @@ namespace clang { namespace transformer { +// Specifies how to interpret an edit. +enum class EditKind { + // Edits a source range in the file. + Range, + // Inserts an include in the file. The `Replacement` field is the name of the + // newly included file. + AddInclude, +}; + /// A concrete description of a source edit, represented by a character range in /// the source to be replaced and a corresponding replacement string. struct Edit { + EditKind Kind = EditKind::Range; CharSourceRange Range; std::string Replacement; llvm::Any Metadata; }; +/// Format of the path in an include directive -- angle brackets or quotes. +enum class IncludeFormat { + Quoted, + Angled, +}; + /// Maps a match result to a list of concrete edits (with possible /// failure). This type is a building block of rewrite rules, but users will /// generally work in terms of `ASTEdit`s (below) rather than directly in terms @@ -47,6 +63,8 @@ using EditGenerator = MatchConsumer<llvm::SmallVector<Edit, 1>>; using TextGenerator = std::shared_ptr<MatchComputation<std::string>>; +using AnyGenerator = MatchConsumer<llvm::Any>; + // Description of a source-code edit, expressed in terms of an AST node. // Includes: an ID for the (bound) node, a selector for source related to the // node, a replacement and, optionally, an explanation for the edit. @@ -84,12 +102,21 @@ using TextGenerator = std::shared_ptr<MatchComputation<std::string>>; // changeTo(cat("different_expr")) // \endcode struct ASTEdit { + EditKind Kind = EditKind::Range; RangeSelector TargetRange; TextGenerator Replacement; TextGenerator Note; - llvm::Any Metadata; + // Not all transformations will want or need to attach metadata and therefore + // should not be required to do so. + AnyGenerator Metadata = [](const ast_matchers::MatchFinder::MatchResult &) + -> llvm::Expected<llvm::Any> { + return llvm::Expected<llvm::Any>(llvm::Any()); + }; }; +/// Generates a single (specified) edit. +EditGenerator edit(ASTEdit E); + /// Lifts a list of `ASTEdit`s into an `EditGenerator`. /// /// The `EditGenerator` will return an empty vector if any of the edits apply to @@ -100,14 +127,130 @@ struct ASTEdit { /// clients. We recommend use of the \c AtomicChange or \c Replacements classes /// for assistance in detecting such conflicts. EditGenerator editList(llvm::SmallVector<ASTEdit, 1> Edits); -// Convenience form of `editList` for a single edit. -EditGenerator edit(ASTEdit); -/// Format of the path in an include directive -- angle brackets or quotes. -enum class IncludeFormat { - Quoted, - Angled, -}; +/// Generates no edits. +inline EditGenerator noEdits() { return editList({}); } + +/// Generates a single, no-op edit anchored at the start location of the +/// specified range. A `noopEdit` may be preferred over `noEdits` to associate a +/// diagnostic `Explanation` with the rule. +EditGenerator noopEdit(RangeSelector Anchor); + +/// Version of `ifBound` specialized to `ASTEdit`. +inline EditGenerator ifBound(std::string ID, ASTEdit TrueEdit, + ASTEdit FalseEdit) { + return ifBound(std::move(ID), edit(std::move(TrueEdit)), + edit(std::move(FalseEdit))); +} + +/// Version of `ifBound` that has no "False" branch. If the node is not bound, +/// then no edits are produced. +inline EditGenerator ifBound(std::string ID, ASTEdit TrueEdit) { + return ifBound(std::move(ID), edit(std::move(TrueEdit)), noEdits()); +} + +/// Flattens a list of generators into a single generator whose elements are the +/// concatenation of the results of the argument generators. +EditGenerator flattenVector(SmallVector<EditGenerator, 2> Generators); + +namespace detail { +/// Helper function to construct an \c EditGenerator. Overloaded for common +/// cases so that user doesn't need to specify which factory function to +/// use. This pattern gives benefits similar to implicit constructors, while +/// maintaing a higher degree of explicitness. +inline EditGenerator injectEdits(ASTEdit E) { return edit(std::move(E)); } +inline EditGenerator injectEdits(EditGenerator G) { return G; } +} // namespace detail + +template <typename... Ts> EditGenerator flatten(Ts &&...Edits) { + return flattenVector({detail::injectEdits(std::forward<Ts>(Edits))...}); +} + +// Every rewrite rule is triggered by a match against some AST node. +// Transformer guarantees that this ID is bound to the triggering node whenever +// a rewrite rule is applied. +extern const char RootID[]; + +/// Replaces a portion of the source text with \p Replacement. +ASTEdit changeTo(RangeSelector Target, TextGenerator Replacement); +/// DEPRECATED: use \c changeTo. +inline ASTEdit change(RangeSelector Target, TextGenerator Replacement) { + return changeTo(std::move(Target), std::move(Replacement)); +} + +/// Replaces the entirety of a RewriteRule's match with \p Replacement. For +/// example, to replace a function call, one could write: +/// \code +/// makeRule(callExpr(callee(functionDecl(hasName("foo")))), +/// changeTo(cat("bar()"))) +/// \endcode +inline ASTEdit changeTo(TextGenerator Replacement) { + return changeTo(node(RootID), std::move(Replacement)); +} +/// DEPRECATED: use \c changeTo. +inline ASTEdit change(TextGenerator Replacement) { + return changeTo(std::move(Replacement)); +} + +/// Inserts \p Replacement before \p S, leaving the source selected by \S +/// unchanged. +inline ASTEdit insertBefore(RangeSelector S, TextGenerator Replacement) { + return changeTo(before(std::move(S)), std::move(Replacement)); +} + +/// Inserts \p Replacement after \p S, leaving the source selected by \S +/// unchanged. +inline ASTEdit insertAfter(RangeSelector S, TextGenerator Replacement) { + return changeTo(after(std::move(S)), std::move(Replacement)); +} + +/// Removes the source selected by \p S. +ASTEdit remove(RangeSelector S); + +/// Adds an include directive for the given header to the file of `Target`. The +/// particular location specified by `Target` is ignored. +ASTEdit addInclude(RangeSelector Target, StringRef Header, + IncludeFormat Format = IncludeFormat::Quoted); + +/// Adds an include directive for the given header to the file associated with +/// `RootID`. If `RootID` matches inside a macro expansion, will add the +/// directive to the file in which the macro was expanded (as opposed to the +/// file in which the macro is defined). +inline ASTEdit addInclude(StringRef Header, + IncludeFormat Format = IncludeFormat::Quoted) { + return addInclude(expansion(node(RootID)), Header, Format); +} + +// FIXME: If `Metadata` returns an `llvm::Expected<T>` the `AnyGenerator` will +// construct an `llvm::Expected<llvm::Any>` where no error is present but the +// `llvm::Any` holds the error. This is unlikely but potentially surprising. +// Perhaps the `llvm::Expected` should be unwrapped, or perhaps this should be a +// compile-time error. No solution here is perfect. +// +// Note: This function template accepts any type callable with a MatchResult +// rather than a `std::function` because the return-type needs to be deduced. If +// it accepted a `std::function<R(MatchResult)>`, lambdas or other callable +// types would not be able to deduce `R`, and users would be forced to specify +// explicitly the type they intended to return by wrapping the lambda at the +// call-site. +template <typename Callable> +inline ASTEdit withMetadata(ASTEdit Edit, Callable Metadata) { + Edit.Metadata = + [Gen = std::move(Metadata)]( + const ast_matchers::MatchFinder::MatchResult &R) -> llvm::Any { + return Gen(R); + }; + + return Edit; +} + +/// Assuming that the inner range is enclosed by the outer range, creates +/// precision edits to remove the parts of the outer range that are not included +/// in the inner range. +inline EditGenerator shrinkTo(RangeSelector outer, RangeSelector inner) { + return editList({remove(enclose(before(outer), before(inner))), + remove(enclose(after(inner), after(outer)))}); +} /// Description of a source-code transformation. // @@ -137,25 +280,19 @@ struct RewriteRule { ast_matchers::internal::DynTypedMatcher Matcher; EditGenerator Edits; TextGenerator Explanation; - // Include paths to add to the file affected by this case. These are - // bundled with the `Case`, rather than the `RewriteRule`, because each case - // might have different associated changes to the includes. - std::vector<std::pair<std::string, IncludeFormat>> AddedIncludes; }; // We expect RewriteRules will most commonly include only one case. SmallVector<Case, 1> Cases; - // ID used as the default target of each match. The node described by the - // matcher is should always be bound to this id. - static constexpr llvm::StringLiteral RootID = "___root___"; + /// DEPRECATED: use `::clang::transformer::RootID` instead. + static const llvm::StringRef RootID; }; -/// Convenience function for constructing a simple \c RewriteRule. +/// Constructs a simple \c RewriteRule. RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M, EditGenerator Edits, TextGenerator Explanation = nullptr); -/// Convenience function for constructing a \c RewriteRule from multiple -/// `ASTEdit`s. +/// Constructs a \c RewriteRule from multiple `ASTEdit`s. inline RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M, llvm::SmallVector<ASTEdit, 1> Edits, TextGenerator Explanation = nullptr) { @@ -163,7 +300,7 @@ inline RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M, std::move(Explanation)); } -/// Convenience overload of \c makeRule for common case of only one edit. +/// Overload of \c makeRule for common case of only one edit. inline RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M, ASTEdit Edit, TextGenerator Explanation = nullptr) { @@ -177,8 +314,8 @@ inline RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M, /// \code /// auto R = makeRule(callExpr(callee(functionDecl(hasName("foo")))), /// changeTo(cat("bar()"))); -/// AddInclude(R, "path/to/bar_header.h"); -/// AddInclude(R, "vector", IncludeFormat::Angled); +/// addInclude(R, "path/to/bar_header.h"); +/// addInclude(R, "vector", IncludeFormat::Angled); /// \endcode void addInclude(RewriteRule &Rule, llvm::StringRef Header, IncludeFormat Format = IncludeFormat::Quoted); @@ -224,47 +361,22 @@ void addInclude(RewriteRule &Rule, llvm::StringRef Header, // ``` RewriteRule applyFirst(ArrayRef<RewriteRule> Rules); -/// Replaces a portion of the source text with \p Replacement. -ASTEdit changeTo(RangeSelector Target, TextGenerator Replacement); -/// DEPRECATED: use \c changeTo. -inline ASTEdit change(RangeSelector Target, TextGenerator Replacement) { - return changeTo(std::move(Target), std::move(Replacement)); -} - -/// Replaces the entirety of a RewriteRule's match with \p Replacement. For -/// example, to replace a function call, one could write: -/// \code -/// makeRule(callExpr(callee(functionDecl(hasName("foo")))), -/// changeTo(cat("bar()"))) -/// \endcode -inline ASTEdit changeTo(TextGenerator Replacement) { - return changeTo(node(std::string(RewriteRule::RootID)), - std::move(Replacement)); -} -/// DEPRECATED: use \c changeTo. -inline ASTEdit change(TextGenerator Replacement) { - return changeTo(std::move(Replacement)); -} - -/// Inserts \p Replacement before \p S, leaving the source selected by \S -/// unchanged. -inline ASTEdit insertBefore(RangeSelector S, TextGenerator Replacement) { - return changeTo(before(std::move(S)), std::move(Replacement)); -} - -/// Inserts \p Replacement after \p S, leaving the source selected by \S -/// unchanged. -inline ASTEdit insertAfter(RangeSelector S, TextGenerator Replacement) { - return changeTo(after(std::move(S)), std::move(Replacement)); -} - -/// Removes the source selected by \p S. -ASTEdit remove(RangeSelector S); - -inline ASTEdit withMetadata(ASTEdit edit, llvm::Any Metadata) { - edit.Metadata = std::move(Metadata); - return edit; -} +/// Applies `Rule` to all descendants of the node bound to `NodeId`. `Rule` can +/// refer to nodes bound by the calling rule. `Rule` is not applied to the node +/// itself. +/// +/// For example, +/// ``` +/// auto InlineX = +/// makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3"))); +/// makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))).bind("f"), +/// flatten( +/// changeTo(name("f"), cat("newName")), +/// rewriteDescendants("body", InlineX))); +/// ``` +/// Here, we find the function `f`, change its name to `newName` and change all +/// appearances of `x` in its body to `3`. +EditGenerator rewriteDescendants(std::string NodeId, RewriteRule Rule); /// The following three functions are a low-level part of the RewriteRule /// API. We expose them for use in implementing the fixtures that interpret @@ -275,6 +387,38 @@ inline ASTEdit withMetadata(ASTEdit edit, llvm::Any Metadata) { // RewriteRule API. Recast them as such. Or, just declare these functions // public and well-supported and move them out of `detail`. namespace detail { +/// The following overload set is a version of `rewriteDescendants` that +/// operates directly on the AST, rather than generating a Transformer +/// combinator. It applies `Rule` to all descendants of `Node`, although not +/// `Node` itself. `Rule` can refer to nodes bound in `Result`. +/// +/// For example, assuming that "body" is bound to a function body in MatchResult +/// `Results`, this will produce edits to change all appearances of `x` in that +/// body to `3`. +/// ``` +/// auto InlineX = +/// makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3"))); +/// const auto *Node = Results.Nodes.getNodeAs<Stmt>("body"); +/// auto Edits = rewriteDescendants(*Node, InlineX, Results); +/// ``` +/// @{ +llvm::Expected<SmallVector<Edit, 1>> +rewriteDescendants(const Decl &Node, RewriteRule Rule, + const ast_matchers::MatchFinder::MatchResult &Result); + +llvm::Expected<SmallVector<Edit, 1>> +rewriteDescendants(const Stmt &Node, RewriteRule Rule, + const ast_matchers::MatchFinder::MatchResult &Result); + +llvm::Expected<SmallVector<Edit, 1>> +rewriteDescendants(const TypeLoc &Node, RewriteRule Rule, + const ast_matchers::MatchFinder::MatchResult &Result); + +llvm::Expected<SmallVector<Edit, 1>> +rewriteDescendants(const DynTypedNode &Node, RewriteRule Rule, + const ast_matchers::MatchFinder::MatchResult &Result); +/// @} + /// Builds a single matcher for the rule, covering all of the rule's cases. /// Only supports Rules whose cases' matchers share the same base "kind" /// (`Stmt`, `Decl`, etc.) Deprecated: use `buildMatchers` instead, which @@ -304,28 +448,6 @@ findSelectedCase(const ast_matchers::MatchFinder::MatchResult &Result, const RewriteRule &Rule); } // namespace detail } // namespace transformer - -namespace tooling { -// DEPRECATED: These are temporary aliases supporting client migration to the -// `transformer` namespace. -/// Wraps a string as a TextGenerator. -using TextGenerator = transformer::TextGenerator; - -TextGenerator text(std::string M); - -using transformer::addInclude; -using transformer::applyFirst; -using transformer::change; -using transformer::insertAfter; -using transformer::insertBefore; -using transformer::makeRule; -using transformer::remove; -using transformer::RewriteRule; -using transformer::IncludeFormat; -namespace detail { -using namespace transformer::detail; -} // namespace detail -} // namespace tooling } // namespace clang #endif // LLVM_CLANG_TOOLING_TRANSFORMER_REWRITE_RULE_H_ diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Transformer/Stencil.h b/contrib/llvm-project/clang/include/clang/Tooling/Transformer/Stencil.h index 1b50a670f70b..1b7495eb0262 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Transformer/Stencil.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Transformer/Stencil.h @@ -82,7 +82,6 @@ Stencil deref(llvm::StringRef ExprId); /// If \p ExprId is of pointer type, constructs an idiomatic dereferencing of /// the expression bound to \p ExprId, including wrapping it in parentheses, if /// needed. Otherwise, generates the original expression source. -/// FIXME: Identify smart-pointers as pointer types. Stencil maybeDeref(llvm::StringRef ExprId); /// Constructs an expression that idiomatically takes the address of the @@ -94,7 +93,6 @@ Stencil addressOf(llvm::StringRef ExprId); /// idiomatically takes the address of the expression bound to \p ExprId, /// including wrapping \p ExprId in parentheses, if needed. Otherwise, generates /// the original expression source. -/// FIXME: Identify smart-pointers as pointer types. Stencil maybeAddressOf(llvm::StringRef ExprId); /// Constructs a `MemberExpr` that accesses the named member (\p Member) of the @@ -123,6 +121,15 @@ inline Stencil ifBound(llvm::StringRef Id, llvm::StringRef TrueText, /// Stencil. This supports user-defined extensions to the \c Stencil language. Stencil run(MatchConsumer<std::string> C); +/// Produces a human-readable rendering of the node bound to `Id`, suitable for +/// diagnostics and debugging. This operator can be applied to any node, but is +/// targeted at those whose source cannot be printed directly, including: +/// +/// * Types. represented based on their structure. Note that namespace +/// qualifiers are always printed, with the anonymous namespace represented +/// explicitly. No desugaring or canonicalization is applied. +Stencil describe(llvm::StringRef Id); + /// For debug use only; semantics are not guaranteed. /// /// \returns the string resulting from calling the node's print() method. |