@@ -61,8 +61,7 @@ enum Name {
61
61
LLVM_ABI bool DisplayGraph (StringRef Filename, bool wait = true ,
62
62
GraphProgram::Name program = GraphProgram::DOT);
63
63
64
- template <typename GraphType>
65
- class GraphWriter {
64
+ template <typename GraphType, typename Derived> class GraphWriterBase {
66
65
raw_ostream &O;
67
66
const GraphType &G;
68
67
bool RenderUsingHTML = false ;
@@ -75,9 +74,15 @@ class GraphWriter {
75
74
DOTTraits DTraits;
76
75
77
76
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
+ }
81
86
82
87
// Writes the edge labels of the node to O and returns true if there are any
83
88
// edge labels not equal to the empty string "".
@@ -118,23 +123,24 @@ class GraphWriter {
118
123
}
119
124
120
125
public:
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) {
122
127
DTraits = DOTTraits (SN);
123
128
RenderUsingHTML = DTraits.renderNodesUsingHTML ();
124
129
}
130
+ virtual ~GraphWriterBase () {}
125
131
126
132
void writeGraph (const std::string &Title = " " ) {
127
133
// Output the header for the graph...
128
- writeHeader (Title);
134
+ getDerived (). writeHeader (Title);
129
135
130
136
// Emit all of the nodes in the graph...
131
- writeNodes ();
137
+ getDerived (). writeNodes ();
132
138
133
139
// Output any customizations on the graph
134
- DOTGraphTraits<GraphType>::addCustomGraphFeatures (G, * this );
140
+ DOTGraphTraits<GraphType>::addCustomGraphFeatures (G, getDerived () );
135
141
136
142
// Output the end of the graph
137
- writeFooter ();
143
+ getDerived (). writeFooter ();
138
144
}
139
145
140
146
void writeHeader (const std::string &Title) {
@@ -166,8 +172,8 @@ class GraphWriter {
166
172
void writeNodes () {
167
173
// Loop over the graph, printing it out...
168
174
for (const auto Node : nodes<GraphType>(G))
169
- if (!isNodeHidden (Node))
170
- writeNode (Node);
175
+ if (!getDerived (). isNodeHidden (Node))
176
+ getDerived (). writeNode (Node);
171
177
}
172
178
173
179
bool isNodeHidden (NodeRef Node) { return DTraits.isNodeHidden (Node, G); }
@@ -302,9 +308,9 @@ class GraphWriter {
302
308
if (DTraits.getEdgeSourceLabel (Node, EI).empty ())
303
309
edgeidx = -1 ;
304
310
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));
308
314
}
309
315
}
310
316
@@ -357,10 +363,17 @@ class GraphWriter {
357
363
}
358
364
};
359
365
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>
361
375
raw_ostream &WriteGraph (raw_ostream &O, const GraphType &G,
362
- bool ShortNames = false ,
363
- const Twine &Title = " " ) {
376
+ bool ShortNames = false , const Twine &Title = " " ) {
364
377
// Start the graph emission process...
365
378
GraphWriter<GraphType> W (O, G, ShortNames);
366
379
0 commit comments