@@ -61,8 +61,7 @@ enum Name {
6161LLVM_ABI bool DisplayGraph (StringRef Filename, bool wait = true ,
6262 GraphProgram::Name program = GraphProgram::DOT);
6363
64- template <typename GraphType>
65- class GraphWriter {
64+ template <typename GraphType, typename Derived> class GraphWriterBase {
6665 raw_ostream &O;
6766 const GraphType &G;
6867 bool RenderUsingHTML = false ;
@@ -75,9 +74,15 @@ class GraphWriter {
7574 DOTTraits DTraits;
7675
7776 static_assert (std::is_pointer_v<NodeRef>,
78- " FIXME: Currently GraphWriter requires the NodeRef type to be "
79- " a pointer.\n The pointer usage should be moved to "
80- " DOTGraphTraits, and removed from GraphWriter itself." );
77+ " FIXME: Currently GraphWriterBase requires the NodeRef type to "
78+ " be a pointer.\n The pointer usage should be moved to "
79+ " DOTGraphTraits, and removed from GraphWriterBase itself." );
80+
81+ // Cast the 'this' pointer to the derived type and return a reference.
82+ Derived &getDerived () { return *static_cast <Derived *>(this ); }
83+ const Derived &getDerived () const {
84+ return *static_cast <const Derived *>(this );
85+ }
8186
8287 // Writes the edge labels of the node to O and returns true if there are any
8388 // edge labels not equal to the empty string "".
@@ -118,23 +123,24 @@ class GraphWriter {
118123 }
119124
120125public:
121- GraphWriter (raw_ostream &o, const GraphType &g, bool SN) : O(o), G(g) {
126+ GraphWriterBase (raw_ostream &o, const GraphType &g, bool SN) : O(o), G(g) {
122127 DTraits = DOTTraits (SN);
123128 RenderUsingHTML = DTraits.renderNodesUsingHTML ();
124129 }
130+ virtual ~GraphWriterBase () {}
125131
126132 void writeGraph (const std::string &Title = " " ) {
127133 // Output the header for the graph...
128- writeHeader (Title);
134+ getDerived (). writeHeader (Title);
129135
130136 // Emit all of the nodes in the graph...
131- writeNodes ();
137+ getDerived (). writeNodes ();
132138
133139 // Output any customizations on the graph
134- DOTGraphTraits<GraphType>::addCustomGraphFeatures (G, * this );
140+ DOTGraphTraits<GraphType>::addCustomGraphFeatures (G, getDerived () );
135141
136142 // Output the end of the graph
137- writeFooter ();
143+ getDerived (). writeFooter ();
138144 }
139145
140146 void writeHeader (const std::string &Title) {
@@ -166,8 +172,8 @@ class GraphWriter {
166172 void writeNodes () {
167173 // Loop over the graph, printing it out...
168174 for (const auto Node : nodes<GraphType>(G))
169- if (!isNodeHidden (Node))
170- writeNode (Node);
175+ if (!getDerived (). isNodeHidden (Node))
176+ getDerived (). writeNode (Node);
171177 }
172178
173179 bool isNodeHidden (NodeRef Node) { return DTraits.isNodeHidden (Node, G); }
@@ -302,9 +308,9 @@ class GraphWriter {
302308 if (DTraits.getEdgeSourceLabel (Node, EI).empty ())
303309 edgeidx = -1 ;
304310
305- emitEdge (static_cast <const void *>(Node), edgeidx,
306- static_cast <const void *>(TargetNode), DestPort,
307- DTraits.getEdgeAttributes (Node, EI, G));
311+ getDerived (). emitEdge (static_cast <const void *>(Node), edgeidx,
312+ static_cast <const void *>(TargetNode), DestPort,
313+ DTraits.getEdgeAttributes (Node, EI, G));
308314 }
309315 }
310316
@@ -357,10 +363,17 @@ class GraphWriter {
357363 }
358364};
359365
360- template <typename GraphType>
366+ template <typename GraphType>
367+ class GraphWriter : public GraphWriterBase <GraphType, GraphWriter<GraphType>> {
368+ public:
369+ GraphWriter (raw_ostream &o, const GraphType &g, bool SN)
370+ : GraphWriterBase<GraphType, GraphWriter<GraphType>>(o, g, SN) {}
371+ ~GraphWriter () override {}
372+ };
373+
374+ template <typename GraphType>
361375raw_ostream &WriteGraph (raw_ostream &O, const GraphType &G,
362- bool ShortNames = false ,
363- const Twine &Title = " " ) {
376+ bool ShortNames = false , const Twine &Title = " " ) {
364377 // Start the graph emission process...
365378 GraphWriter<GraphType> W (O, G, ShortNames);
366379
0 commit comments