|
|
|||
File indexing completed on 2026-05-10 08:37:12
0001 //===--- Stencil.h - Stencil class ------------------------------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 /// 0009 /// \file 0010 /// This file defines the *Stencil* abstraction: a code-generating object, 0011 /// parameterized by named references to (bound) AST nodes. Given a match 0012 /// result, a stencil can be evaluated to a string of source code. 0013 /// 0014 /// A stencil is similar in spirit to a format string: it is composed of a 0015 /// series of raw text strings, references to nodes (the parameters) and helper 0016 /// code-generation operations. 0017 /// 0018 //===----------------------------------------------------------------------===// 0019 0020 #ifndef LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_ 0021 #define LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_ 0022 0023 #include "clang/AST/ASTContext.h" 0024 #include "clang/AST/ASTTypeTraits.h" 0025 #include "clang/ASTMatchers/ASTMatchFinder.h" 0026 #include "clang/Tooling/Transformer/MatchConsumer.h" 0027 #include "clang/Tooling/Transformer/RangeSelector.h" 0028 #include "llvm/ADT/StringRef.h" 0029 #include "llvm/Support/Error.h" 0030 #include <string> 0031 #include <vector> 0032 0033 namespace clang { 0034 namespace transformer { 0035 0036 using StencilInterface = MatchComputation<std::string>; 0037 0038 /// A sequence of code fragments, references to parameters and code-generation 0039 /// operations that together can be evaluated to (a fragment of) source code or 0040 /// a diagnostic message, given a match result. 0041 /// 0042 /// We use a `shared_ptr` to allow for easy and cheap copying of stencils. 0043 /// Since `StencilInterface` is an immutable interface, the sharing doesn't 0044 /// impose any risks. Otherwise, we would have to add a virtual `copy` method to 0045 /// the API and implement it for all derived classes. 0046 using Stencil = std::shared_ptr<StencilInterface>; 0047 0048 namespace detail { 0049 /// Convenience function to construct a \c Stencil. Overloaded for common cases 0050 /// so that user doesn't need to specify which factory function to use. This 0051 /// pattern gives benefits similar to implicit constructors, while maintaing a 0052 /// higher degree of explicitness. 0053 Stencil makeStencil(llvm::StringRef Text); 0054 Stencil makeStencil(RangeSelector Selector); 0055 inline Stencil makeStencil(Stencil S) { return S; } 0056 } // namespace detail 0057 0058 /// Constructs the string representing the concatenation of the given \p 0059 /// Parts. If only one element is passed in \p Parts, returns that element. 0060 Stencil catVector(std::vector<Stencil> Parts); 0061 0062 /// Concatenates 0+ stencil pieces into a single stencil. Arguments can be raw 0063 /// text, ranges in the matched code (\p RangeSelector) or other `Stencil`s. 0064 template <typename... Ts> Stencil cat(Ts &&... Parts) { 0065 return catVector({detail::makeStencil(std::forward<Ts>(Parts))...}); 0066 } 0067 0068 // 0069 // Functions for conveniently building stencils. 0070 // 0071 0072 /// Generates the source of the expression bound to \p Id, wrapping it in 0073 /// parentheses if it may parse differently depending on context. For example, a 0074 /// binary operation is always wrapped, while a variable reference is never 0075 /// wrapped. 0076 Stencil expression(llvm::StringRef Id); 0077 0078 /// Constructs an idiomatic dereferencing of the expression bound to \p ExprId. 0079 /// \p ExprId is wrapped in parentheses, if needed. 0080 Stencil deref(llvm::StringRef ExprId); 0081 0082 /// If \p ExprId is of pointer type, constructs an idiomatic dereferencing of 0083 /// the expression bound to \p ExprId, including wrapping it in parentheses, if 0084 /// needed. Otherwise, generates the original expression source. 0085 Stencil maybeDeref(llvm::StringRef ExprId); 0086 0087 /// Constructs an expression that idiomatically takes the address of the 0088 /// expression bound to \p ExprId. \p ExprId is wrapped in parentheses, if 0089 /// needed. 0090 Stencil addressOf(llvm::StringRef ExprId); 0091 0092 /// If \p ExprId is not a pointer type, constructs an expression that 0093 /// idiomatically takes the address of the expression bound to \p ExprId, 0094 /// including wrapping \p ExprId in parentheses, if needed. Otherwise, generates 0095 /// the original expression source. 0096 Stencil maybeAddressOf(llvm::StringRef ExprId); 0097 0098 /// Constructs a `MemberExpr` that accesses the named member (\p Member) of the 0099 /// object bound to \p BaseId. The access is constructed idiomatically: if \p 0100 /// BaseId is bound to `e` and \p Member identifies member `m`, then returns 0101 /// `e->m`, when e is a pointer, `e2->m` when e = `*e2` and `e.m` otherwise. 0102 /// Additionally, `e` is wrapped in parentheses, if needed. 0103 Stencil access(llvm::StringRef BaseId, Stencil Member); 0104 inline Stencil access(llvm::StringRef BaseId, llvm::StringRef Member) { 0105 return access(BaseId, detail::makeStencil(Member)); 0106 } 0107 0108 /// Chooses between the two stencil parts, based on whether \p ID is bound in 0109 /// the match. 0110 Stencil ifBound(llvm::StringRef Id, Stencil TrueStencil, Stencil FalseStencil); 0111 0112 /// Chooses between the two strings, based on whether \p ID is bound in the 0113 /// match. 0114 inline Stencil ifBound(llvm::StringRef Id, llvm::StringRef TrueText, 0115 llvm::StringRef FalseText) { 0116 return ifBound(Id, detail::makeStencil(TrueText), 0117 detail::makeStencil(FalseText)); 0118 } 0119 0120 /// Chooses between multiple stencils, based on the presence of bound nodes. \p 0121 /// CaseStencils takes a vector of (ID, \c Stencil) pairs and checks each ID in 0122 /// order to see if it's bound to a node. If so, the associated \c Stencil is 0123 /// run and all other cases are ignored. An optional \p DefaultStencil can be 0124 /// provided to be run if all cases are exhausted beacause none of the provided 0125 /// IDs are bound. If no default case is provided and all cases are exhausted, 0126 /// the stencil will fail with error `llvm::errc::result_out_of_range`. 0127 /// 0128 /// For example, say one matches a statement's type with: 0129 /// anyOf( 0130 /// qualType(isInteger()).bind("int"), 0131 /// qualType(realFloatingPointType()).bind("float"), 0132 /// qualType(isAnyCharacter()).bind("char"), 0133 /// booleanType().bind("bool")) 0134 /// 0135 /// Then, one can decide in a stencil how to construct a literal. 0136 /// cat("a = ", 0137 /// selectBound( 0138 /// {{"int", cat("0")}, 0139 /// {"float", cat("0.0")}, 0140 /// {"char", cat("'\\0'")}, 0141 /// {"bool", cat("false")}})) 0142 /// 0143 /// In addition, one could supply a default case for all other types: 0144 /// selectBound( 0145 /// {{"int", cat("0")}, 0146 /// ... 0147 /// {"bool", cat("false")}}, 0148 /// cat("{}")) 0149 Stencil selectBound(std::vector<std::pair<std::string, Stencil>> CaseStencils, 0150 Stencil DefaultStencil = nullptr); 0151 0152 /// Wraps a \c MatchConsumer in a \c Stencil, so that it can be used in a \c 0153 /// Stencil. This supports user-defined extensions to the \c Stencil language. 0154 Stencil run(MatchConsumer<std::string> C); 0155 0156 /// Produces a human-readable rendering of the node bound to `Id`, suitable for 0157 /// diagnostics and debugging. This operator can be applied to any node, but is 0158 /// targeted at those whose source cannot be printed directly, including: 0159 /// 0160 /// * Types. represented based on their structure. Note that namespace 0161 /// qualifiers are always printed, with the anonymous namespace represented 0162 /// explicitly. No desugaring or canonicalization is applied. 0163 Stencil describe(llvm::StringRef Id); 0164 0165 /// For debug use only; semantics are not guaranteed. 0166 /// 0167 /// \returns the string resulting from calling the node's print() method. 0168 Stencil dPrint(llvm::StringRef Id); 0169 } // namespace transformer 0170 } // namespace clang 0171 #endif // LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|