diff --git a/clang/include/clang/Tooling/Transformer/Stencil.h b/clang/include/clang/Tooling/Transformer/Stencil.h --- a/clang/include/clang/Tooling/Transformer/Stencil.h +++ b/clang/include/clang/Tooling/Transformer/Stencil.h @@ -48,26 +48,18 @@ virtual llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &Match, std::string *Result) const = 0; - virtual bool isEqual(const StencilPartInterface &other) const = 0; - /// Constructs a string representation of the StencilPart. StencilParts /// generated by the `selection` and `run` functions do not have a unique /// string representation. virtual std::string toString() const = 0; - const void *typeId() const { return TypeId; } - protected: - StencilPartInterface(const void *DerivedId) : TypeId(DerivedId) {} + StencilPartInterface() = default; // Since this is an abstract class, copying/assigning only make sense for // derived classes implementing `clone()`. StencilPartInterface(const StencilPartInterface &) = default; StencilPartInterface &operator=(const StencilPartInterface &) = default; - - /// Unique identifier of the concrete type of this instance. Supports safe - /// downcasting. - const void *TypeId; }; /// A copyable facade for a std::unique_ptr. Copies result @@ -83,14 +75,6 @@ return Impl->eval(Match, Result); } - bool operator==(const StencilPart &Other) const { - if (Impl == Other.Impl) - return true; - if (Impl == nullptr || Other.Impl == nullptr) - return false; - return Impl->isEqual(*Other.Impl); - } - std::string toString() const { if (Impl == nullptr) return ""; @@ -142,7 +126,6 @@ } private: - friend bool operator==(const Stencil &A, const Stencil &B); static StencilPart wrap(llvm::StringRef Text); static StencilPart wrap(RangeSelector Selector); static StencilPart wrap(StencilPart Part) { return Part; } @@ -150,12 +133,6 @@ std::vector Parts; }; -inline bool operator==(const Stencil &A, const Stencil &B) { - return A.Parts == B.Parts; -} - -inline bool operator!=(const Stencil &A, const Stencil &B) { return !(A == B); } - // Functions for conveniently building stencils. namespace stencil { /// Convenience wrapper for Stencil::cat that can be imported with a using decl. diff --git a/clang/lib/Tooling/Transformer/Stencil.cpp b/clang/lib/Tooling/Transformer/Stencil.cpp --- a/clang/lib/Tooling/Transformer/Stencil.cpp +++ b/clang/lib/Tooling/Transformer/Stencil.cpp @@ -31,14 +31,6 @@ using llvm::Expected; using llvm::StringError; -// A down_cast function to safely down cast a StencilPartInterface to a subclass -// D. Returns nullptr if P is not an instance of D. -template const D *down_cast(const StencilPartInterface *P) { - if (P == nullptr || D::typeId() != P->typeId()) - return nullptr; - return static_cast(P); -} - static llvm::Expected getNode(const ast_matchers::BoundNodes &Nodes, StringRef Id) { auto &NodesMap = Nodes.getMap(); @@ -100,35 +92,6 @@ StencilPart FalsePart; }; -bool isEqualData(const RawTextData &A, const RawTextData &B) { - return A.Text == B.Text; -} - -bool isEqualData(const DebugPrintNodeData &A, const DebugPrintNodeData &B) { - return A.Id == B.Id; -} - -bool isEqualData(const UnaryOperationData &A, const UnaryOperationData &B) { - return A.Op == B.Op && A.Id == B.Id; -} - -// Equality is not (yet) defined for \c RangeSelector. -bool isEqualData(const SelectorData &, const SelectorData &) { return false; } - -bool isEqualData(const AccessData &A, const AccessData &B) { - return A.BaseId == B.BaseId && A.Member == B.Member; -} - -bool isEqualData(const IfBoundData &A, const IfBoundData &B) { - return A.Id == B.Id && A.TruePart == B.TruePart && A.FalsePart == B.FalsePart; -} - -// Equality is not defined over MatchConsumers, which are opaque. -bool isEqualData(const MatchConsumer &A, - const MatchConsumer &B) { - return false; -} - std::string toStringData(const RawTextData &Data) { std::string Result; llvm::raw_string_ostream OS(Result); @@ -159,7 +122,7 @@ return (OpName + "(\"" + Data.Id + "\")").str(); } -std::string toStringData(const SelectorData &) { return "SelectorData()"; } +std::string toStringData(const SelectorData &) { return "selection(...)"; } std::string toStringData(const AccessData &Data) { return (llvm::Twine("access(\"") + Data.BaseId + "\", " + @@ -174,7 +137,7 @@ } std::string toStringData(const MatchConsumer &) { - return "MatchConsumer()"; + return "run(...)"; } // The `evalData()` overloads evaluate the given stencil data to a string, given @@ -275,28 +238,13 @@ public: template - explicit StencilPartImpl(Ps &&... Args) - : StencilPartInterface(StencilPartImpl::typeId()), - Data(std::forward(Args)...) {} - - // Generates a unique identifier for this class (specifically, one per - // instantiation of the template). - static const void* typeId() { - static bool b; - return &b; - } + explicit StencilPartImpl(Ps &&... Args) : Data(std::forward(Args)...) {} Error eval(const MatchFinder::MatchResult &Match, std::string *Result) const override { return evalData(Data, Match, Result); } - bool isEqual(const StencilPartInterface &Other) const override { - if (const auto *OtherPtr = down_cast(&Other)) - return isEqualData(Data, OtherPtr->Data); - return false; - } - std::string toString() const override { return toStringData(Data); } }; } // namespace diff --git a/clang/unittests/Tooling/StencilTest.cpp b/clang/unittests/Tooling/StencilTest.cpp --- a/clang/unittests/Tooling/StencilTest.cpp +++ b/clang/unittests/Tooling/StencilTest.cpp @@ -357,39 +357,6 @@ testExpr(Id, "3;", cat(run(SimpleFn)), "Bound"); } -TEST(StencilEqualityTest, Equality) { - auto Lhs = cat("foo", dPrint("dprint_id")); - auto Rhs = cat("foo", dPrint("dprint_id")); - EXPECT_EQ(Lhs, Rhs); -} - -TEST(StencilEqualityTest, InEqualityDifferentOrdering) { - auto Lhs = cat("foo", dPrint("node")); - auto Rhs = cat(dPrint("node"), "foo"); - EXPECT_NE(Lhs, Rhs); -} - -TEST(StencilEqualityTest, InEqualityDifferentSizes) { - auto Lhs = cat("foo", dPrint("node"), "bar", "baz"); - auto Rhs = cat("foo", dPrint("node"), "bar"); - EXPECT_NE(Lhs, Rhs); -} - -// node is opaque and therefore cannot be examined for equality. -TEST(StencilEqualityTest, InEqualitySelection) { - auto S1 = cat(node("node")); - auto S2 = cat(node("node")); - EXPECT_NE(S1, S2); -} - -// `run` is opaque. -TEST(StencilEqualityTest, InEqualityRun) { - auto F = [](const MatchResult &R) { return "foo"; }; - auto S1 = cat(run(F)); - auto S2 = cat(run(F)); - EXPECT_NE(S1, S2); -} - TEST(StencilToStringTest, RawTextOp) { auto S = cat("foo bar baz"); StringRef Expected = R"("foo bar baz")"; @@ -426,6 +393,11 @@ EXPECT_EQ(S.toString(), Expected); } +TEST(StencilToStringTest, SelectionOp) { + auto S1 = cat(node("node1")); + EXPECT_EQ(S1.toString(), "selection(...)"); +} + TEST(StencilToStringTest, AccessOp) { auto S = cat(access("Id", text("memberData"))); StringRef Expected = R"repr(access("Id", "memberData"))repr"; @@ -445,6 +417,12 @@ EXPECT_EQ(S.toString(), Expected); } +TEST(StencilToStringTest, RunOp) { + auto F1 = [](const MatchResult &R) { return "foo"; }; + auto S1 = cat(run(F1)); + EXPECT_EQ(S1.toString(), "run(...)"); +} + TEST(StencilToStringTest, MultipleOp) { auto S = cat("foo", access("x", "m()"), "bar", ifBound("x", text("t"), access("e", "f")));