]> granicus.if.org Git - clang/commitdiff
[libTooling] Change Stencil equality to use `toString()`
authorYitzhak Mandelbaum <yitzhakm@google.com>
Fri, 11 Oct 2019 14:02:03 +0000 (14:02 +0000)
committerYitzhak Mandelbaum <yitzhakm@google.com>
Fri, 11 Oct 2019 14:02:03 +0000 (14:02 +0000)
Summary:
Removes the `isEqual` method from StencilPartInterface and modifies equality to
use the string representation returned by the `toString` method for comparison.

This means the `run` and `selection` stencils return true by default, and
clients should be cautious in relying on equality operator for comparison of
stencils containing parts generated by these functions.

It also means we no longer need the custom RTTI support (typeId() and
down_cast()), so it has been removed.

Patch by Harshal T. Lehri.

Reviewers: gribozavr

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D68825

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@374552 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Tooling/Transformer/Stencil.h
lib/Tooling/Transformer/Stencil.cpp
unittests/Tooling/StencilTest.cpp

index 617585cacdbfb5ac62ad499fa261deb180b3ff26..eeb590244402cf4928250a25df244bb93c231bbd 100644 (file)
@@ -48,26 +48,18 @@ public:
   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<StencilPartInterface>. Copies result
@@ -83,14 +75,6 @@ public:
     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 @@ public:
   }
 
 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 @@ private:
   std::vector<StencilPart> 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.
index 82fde2bc4db02df6efec20787619574c175a053c..d252449418a85d74c16821cd6fce67b49caa4214 100644 (file)
@@ -31,14 +31,6 @@ using llvm::Error;
 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 <typename D> const D *down_cast(const StencilPartInterface *P) {
-  if (P == nullptr || D::typeId() != P->typeId())
-    return nullptr;
-  return static_cast<const D *>(P);
-}
-
 static llvm::Expected<DynTypedNode>
 getNode(const ast_matchers::BoundNodes &Nodes, StringRef Id) {
   auto &NodesMap = Nodes.getMap();
@@ -100,35 +92,6 @@ struct IfBoundData {
   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<std::string> &A,
-                 const MatchConsumer<std::string> &B) {
-  return false;
-}
-
 std::string toStringData(const RawTextData &Data) {
   std::string Result;
   llvm::raw_string_ostream OS(Result);
@@ -159,7 +122,7 @@ std::string toStringData(const UnaryOperationData &Data) {
   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 IfBoundData &Data) {
 }
 
 std::string toStringData(const MatchConsumer<std::string> &) {
-  return "MatchConsumer<std::string>()";
+  return "run(...)";
 }
 
 // The `evalData()` overloads evaluate the given stencil data to a string, given
@@ -275,28 +238,13 @@ class StencilPartImpl : public StencilPartInterface {
 
 public:
   template <typename... Ps>
-  explicit StencilPartImpl(Ps &&... Args)
-      : StencilPartInterface(StencilPartImpl::typeId()),
-        Data(std::forward<Ps>(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<Ps>(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<StencilPartImpl>(&Other))
-      return isEqualData(Data, OtherPtr->Data);
-    return false;
-  }
-
   std::string toString() const override { return toStringData(Data); }
 };
 } // namespace
index 2b9aa68e34c97eb3d089bcd30ab1b516bf5d76e3..c524441bebb502f3e6b69716c977456060ec9dad 100644 (file)
@@ -357,39 +357,6 @@ TEST_F(StencilTest, RunOp) {
   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 @@ TEST(StencilToStringTest, AddressOfOp) {
   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 @@ TEST(StencilToStringTest, IfBoundOp) {
   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")));