summaryrefslogtreecommitdiff
path: root/clang/lib/Tooling/Transformer/Stencil.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
commit706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch)
tree4adf86a776049cbf7f69a1929c4babcbbef925eb /clang/lib/Tooling/Transformer/Stencil.cpp
parent7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff)
Notes
Diffstat (limited to 'clang/lib/Tooling/Transformer/Stencil.cpp')
-rw-r--r--clang/lib/Tooling/Transformer/Stencil.cpp160
1 files changed, 101 insertions, 59 deletions
diff --git a/clang/lib/Tooling/Transformer/Stencil.cpp b/clang/lib/Tooling/Transformer/Stencil.cpp
index 984950a54e96..8710e3cdf60f 100644
--- a/clang/lib/Tooling/Transformer/Stencil.cpp
+++ b/clang/lib/Tooling/Transformer/Stencil.cpp
@@ -15,6 +15,7 @@
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/Transformer/SourceCode.h"
#include "clang/Tooling/Transformer/SourceCodeBuilders.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Errc.h"
#include <atomic>
@@ -58,7 +59,9 @@ struct DebugPrintNodeData {
enum class UnaryNodeOperator {
Parens,
Deref,
- Address,
+ MaybeDeref,
+ AddressOf,
+ MaybeAddressOf,
};
// Generic container for stencil operations with a (single) node-id argument.
@@ -77,19 +80,24 @@ struct SelectorData {
// A stencil operation to build a member access `e.m` or `e->m`, as appropriate.
struct AccessData {
- AccessData(StringRef BaseId, StencilPart Member)
+ AccessData(StringRef BaseId, Stencil Member)
: BaseId(BaseId), Member(std::move(Member)) {}
std::string BaseId;
- StencilPart Member;
+ Stencil Member;
};
struct IfBoundData {
- IfBoundData(StringRef Id, StencilPart TruePart, StencilPart FalsePart)
- : Id(Id), TruePart(std::move(TruePart)), FalsePart(std::move(FalsePart)) {
- }
+ IfBoundData(StringRef Id, Stencil TrueStencil, Stencil FalseStencil)
+ : Id(Id), TrueStencil(std::move(TrueStencil)),
+ FalseStencil(std::move(FalseStencil)) {}
std::string Id;
- StencilPart TruePart;
- StencilPart FalsePart;
+ Stencil TrueStencil;
+ Stencil FalseStencil;
+};
+
+struct SequenceData {
+ SequenceData(std::vector<Stencil> Stencils) : Stencils(std::move(Stencils)) {}
+ std::vector<Stencil> Stencils;
};
std::string toStringData(const RawTextData &Data) {
@@ -115,9 +123,15 @@ std::string toStringData(const UnaryOperationData &Data) {
case UnaryNodeOperator::Deref:
OpName = "deref";
break;
- case UnaryNodeOperator::Address:
+ case UnaryNodeOperator::MaybeDeref:
+ OpName = "maybeDeref";
+ break;
+ case UnaryNodeOperator::AddressOf:
OpName = "addressOf";
break;
+ case UnaryNodeOperator::MaybeAddressOf:
+ OpName = "maybeAddressOf";
+ break;
}
return (OpName + "(\"" + Data.Id + "\")").str();
}
@@ -126,13 +140,14 @@ std::string toStringData(const SelectorData &) { return "selection(...)"; }
std::string toStringData(const AccessData &Data) {
return (llvm::Twine("access(\"") + Data.BaseId + "\", " +
- Data.Member.toString() + ")")
+ Data.Member->toString() + ")")
.str();
}
std::string toStringData(const IfBoundData &Data) {
return (llvm::Twine("ifBound(\"") + Data.Id + "\", " +
- Data.TruePart.toString() + ", " + Data.FalsePart.toString() + ")")
+ Data.TrueStencil->toString() + ", " + Data.FalseStencil->toString() +
+ ")")
.str();
}
@@ -140,6 +155,14 @@ std::string toStringData(const MatchConsumer<std::string> &) {
return "run(...)";
}
+std::string toStringData(const SequenceData &Data) {
+ llvm::SmallVector<std::string, 2> Parts;
+ Parts.reserve(Data.Stencils.size());
+ for (const auto &S : Data.Stencils)
+ Parts.push_back(S->toString());
+ return (llvm::Twine("seq(") + llvm::join(Parts, ", ") + ")").str();
+}
+
// The `evalData()` overloads evaluate the given stencil data to a string, given
// the match result, and append it to `Result`. We define an overload for each
// type of stencil data.
@@ -176,7 +199,21 @@ Error evalData(const UnaryOperationData &Data,
case UnaryNodeOperator::Deref:
Source = tooling::buildDereference(*E, *Match.Context);
break;
- case UnaryNodeOperator::Address:
+ case UnaryNodeOperator::MaybeDeref:
+ if (!E->getType()->isAnyPointerType()) {
+ *Result += tooling::getText(*E, *Match.Context);
+ return Error::success();
+ }
+ Source = tooling::buildDereference(*E, *Match.Context);
+ break;
+ case UnaryNodeOperator::AddressOf:
+ Source = tooling::buildAddressOf(*E, *Match.Context);
+ break;
+ case UnaryNodeOperator::MaybeAddressOf:
+ if (E->getType()->isAnyPointerType()) {
+ *Result += tooling::getText(*E, *Match.Context);
+ return Error::success();
+ }
Source = tooling::buildAddressOf(*E, *Match.Context);
break;
}
@@ -214,14 +251,14 @@ Error evalData(const AccessData &Data, const MatchFinder::MatchResult &Match,
errc::invalid_argument,
"Could not construct object text from ID: " + Data.BaseId);
}
- return Data.Member.eval(Match, Result);
+ return Data.Member->eval(Match, Result);
}
Error evalData(const IfBoundData &Data, const MatchFinder::MatchResult &Match,
std::string *Result) {
auto &M = Match.Nodes.getMap();
- return (M.find(Data.Id) != M.end() ? Data.TruePart : Data.FalsePart)
- .eval(Match, Result);
+ return (M.find(Data.Id) != M.end() ? Data.TrueStencil : Data.FalseStencil)
+ ->eval(Match, Result);
}
Error evalData(const MatchConsumer<std::string> &Fn,
@@ -233,13 +270,20 @@ Error evalData(const MatchConsumer<std::string> &Fn,
return Error::success();
}
-template <typename T>
-class StencilPartImpl : public StencilPartInterface {
+Error evalData(const SequenceData &Data, const MatchFinder::MatchResult &Match,
+ std::string *Result) {
+ for (const auto &S : Data.Stencils)
+ if (auto Err = S->eval(Match, Result))
+ return Err;
+ return Error::success();
+}
+
+template <typename T> class StencilImpl : public StencilInterface {
T Data;
public:
template <typename... Ps>
- explicit StencilPartImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
+ explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
Error eval(const MatchFinder::MatchResult &Match,
std::string *Result) const override {
@@ -250,69 +294,67 @@ public:
};
} // namespace
-StencilPart Stencil::wrap(StringRef Text) {
- return transformer::text(Text);
+Stencil transformer::detail::makeStencil(StringRef Text) { return text(Text); }
+
+Stencil transformer::detail::makeStencil(RangeSelector Selector) {
+ return selection(std::move(Selector));
}
-StencilPart Stencil::wrap(RangeSelector Selector) {
- return transformer::selection(std::move(Selector));
+Stencil transformer::text(StringRef Text) {
+ return std::make_shared<StencilImpl<RawTextData>>(Text);
}
-void Stencil::append(Stencil OtherStencil) {
- for (auto &Part : OtherStencil.Parts)
- Parts.push_back(std::move(Part));
+Stencil transformer::selection(RangeSelector Selector) {
+ return std::make_shared<StencilImpl<SelectorData>>(std::move(Selector));
}
-llvm::Expected<std::string>
-Stencil::eval(const MatchFinder::MatchResult &Match) const {
- std::string Result;
- for (const auto &Part : Parts)
- if (auto Err = Part.eval(Match, &Result))
- return std::move(Err);
- return Result;
+Stencil transformer::dPrint(StringRef Id) {
+ return std::make_shared<StencilImpl<DebugPrintNodeData>>(Id);
}
-StencilPart transformer::text(StringRef Text) {
- return StencilPart(std::make_shared<StencilPartImpl<RawTextData>>(Text));
+Stencil transformer::expression(llvm::StringRef Id) {
+ return std::make_shared<StencilImpl<UnaryOperationData>>(
+ UnaryNodeOperator::Parens, Id);
}
-StencilPart transformer::selection(RangeSelector Selector) {
- return StencilPart(
- std::make_shared<StencilPartImpl<SelectorData>>(std::move(Selector)));
+Stencil transformer::deref(llvm::StringRef ExprId) {
+ return std::make_shared<StencilImpl<UnaryOperationData>>(
+ UnaryNodeOperator::Deref, ExprId);
}
-StencilPart transformer::dPrint(StringRef Id) {
- return StencilPart(std::make_shared<StencilPartImpl<DebugPrintNodeData>>(Id));
+Stencil transformer::maybeDeref(llvm::StringRef ExprId) {
+ return std::make_shared<StencilImpl<UnaryOperationData>>(
+ UnaryNodeOperator::MaybeDeref, ExprId);
}
-StencilPart transformer::expression(llvm::StringRef Id) {
- return StencilPart(std::make_shared<StencilPartImpl<UnaryOperationData>>(
- UnaryNodeOperator::Parens, Id));
+Stencil transformer::addressOf(llvm::StringRef ExprId) {
+ return std::make_shared<StencilImpl<UnaryOperationData>>(
+ UnaryNodeOperator::AddressOf, ExprId);
}
-StencilPart transformer::deref(llvm::StringRef ExprId) {
- return StencilPart(std::make_shared<StencilPartImpl<UnaryOperationData>>(
- UnaryNodeOperator::Deref, ExprId));
+Stencil transformer::maybeAddressOf(llvm::StringRef ExprId) {
+ return std::make_shared<StencilImpl<UnaryOperationData>>(
+ UnaryNodeOperator::MaybeAddressOf, ExprId);
}
-StencilPart transformer::addressOf(llvm::StringRef ExprId) {
- return StencilPart(std::make_shared<StencilPartImpl<UnaryOperationData>>(
- UnaryNodeOperator::Address, ExprId));
+Stencil transformer::access(StringRef BaseId, Stencil Member) {
+ return std::make_shared<StencilImpl<AccessData>>(BaseId, std::move(Member));
}
-StencilPart transformer::access(StringRef BaseId, StencilPart Member) {
- return StencilPart(
- std::make_shared<StencilPartImpl<AccessData>>(BaseId, std::move(Member)));
+Stencil transformer::ifBound(StringRef Id, Stencil TrueStencil,
+ Stencil FalseStencil) {
+ return std::make_shared<StencilImpl<IfBoundData>>(Id, std::move(TrueStencil),
+ std::move(FalseStencil));
}
-StencilPart transformer::ifBound(StringRef Id, StencilPart TruePart,
- StencilPart FalsePart) {
- return StencilPart(std::make_shared<StencilPartImpl<IfBoundData>>(
- Id, std::move(TruePart), std::move(FalsePart)));
+Stencil transformer::run(MatchConsumer<std::string> Fn) {
+ return std::make_shared<StencilImpl<MatchConsumer<std::string>>>(
+ std::move(Fn));
}
-StencilPart transformer::run(MatchConsumer<std::string> Fn) {
- return StencilPart(
- std::make_shared<StencilPartImpl<MatchConsumer<std::string>>>(
- std::move(Fn)));
+Stencil transformer::catVector(std::vector<Stencil> Parts) {
+ // Only one argument, so don't wrap in sequence.
+ if (Parts.size() == 1)
+ return std::move(Parts[0]);
+ return std::make_shared<StencilImpl<SequenceData>>(std::move(Parts));
}