svf-lib 1.0.1055 → 1.0.1058

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,8 +27,8 @@
27
27
  * Author: Pei Xu
28
28
  */
29
29
 
30
- #ifndef CFGNormalizer_H_
31
- #define CFGNormalizer_H_
30
+ #ifndef INCLUDE_CFL_CFGNormalizer_H_
31
+ #define INCLUDE_CFL_CFGNormalizer_H_
32
32
 
33
33
  #include "CFLGrammar.h"
34
34
 
@@ -36,7 +36,12 @@ namespace SVF
36
36
  {
37
37
 
38
38
  /*!
39
- * Normalize Grammar from a grammarbase
39
+ * Generate Normalized Grammar from a grammarbase
40
+ *
41
+ * To Do:
42
+ * Error Notice for ill formed production,
43
+ * e.g. not end with ';' and '*' not preceding with '()' and extra space before ';'
44
+ * '|' sign support
40
45
  */
41
46
 
42
47
  class CFGNormalizer
@@ -47,23 +52,23 @@ public:
47
52
  {
48
53
  }
49
54
 
50
- /// Normalization with attribute expanded
55
+ /// Binary Normal Form(BNF) normalization with variable attribute expanded
51
56
  CFLGrammar* normalize(GrammarBase *generalGrammar);
52
57
 
53
- /// Fill Every attribute in CFL grammar
58
+ /// Expand every variable attribute in rawProductions of grammarbase
54
59
  CFLGrammar* fillAttribute(CFLGrammar *grammar, const Map<CFLGrammar::Kind, Set<CFLGrammar::Attribute>>& kind2AttrsMap);
55
60
 
56
61
  private:
57
62
  /// Add nonterminal to tranfer long rules to binary rules
58
63
  void ebnf_bin(CFLGrammar *grammar);
59
64
 
60
- void ebnf_sign_replace(char sign, CFLGrammar *grammar);
65
+ void ebnfSignReplace(char sign, CFLGrammar *grammar);
61
66
 
62
67
  void insertToCFLGrammar(CFLGrammar *grammar, GrammarBase::Production &prod);
63
68
 
64
- int ebnf_bracket_match(GrammarBase::Production& prod, int i, CFLGrammar *grammar) ;
69
+ int ebnfBracketMatch(GrammarBase::Production& prod, int i, CFLGrammar *grammar) ;
65
70
 
66
- int check_head(Map<GrammarBase::Symbol, GrammarBase::Productions>& grammar, GrammarBase::Production& rule);
71
+ GrammarBase::Symbol check_head(GrammarBase::SymbolMap<GrammarBase::Symbol, GrammarBase::Productions>& grammar, GrammarBase::Production& rule);
67
72
 
68
73
  GrammarBase::Production strTrans(std::string strPro, CFLGrammar *grammar);
69
74
 
@@ -74,4 +79,4 @@ private:
74
79
 
75
80
  } // End namespace SVF
76
81
 
77
- #endif /* CFGNormalizer_H_*/
82
+ #endif /* INCLUDE_CFL_CFGNormalizer_H_*/
@@ -51,50 +51,11 @@ public:
51
51
  /// Destructor
52
52
  virtual ~CFLAlias()
53
53
  {
54
- delete graph;
55
- delete grammar;
56
54
  delete solver;
57
55
  }
58
56
 
59
57
  /// Start Analysis here (main part of pointer analysis).
60
- virtual void analyze()
61
- {
62
- GrammarBuilder gReader = GrammarBuilder(Options::GrammarFilename);
63
- CFGNormalizer normalizer = CFGNormalizer();
64
- CFLGraphBuilder cflGraphBuilder = CFLGraphBuilder();
65
- CFLGramGraphChecker cflChecker = CFLGramGraphChecker();
66
- /// Assume Read From Const Graph, associate label symbol is hard coded
67
- if (Options::GraphIsFromDot == false)
68
- {
69
- PointerAnalysis::initialize();
70
- Map<std::string, SVF::CFLGraph::Symbol> ConstMap = {{"Addr",0}, {"Copy", 1},{"Store", 2},{"Load", 3},{"Gep_i", 4},{"Vgep", 5},{"Addrbar",6}, {"Copybar", 7},{"Storebar", 8},{"Loadbar", 9},{"Gepbar_i", 10},{"Vgepbar", 11}};
71
- GrammarBase *generalGrammar = gReader.build(ConstMap);
72
- ConstraintGraph *consCG = new ConstraintGraph(svfir);
73
- graph = cflGraphBuilder.buildBigraph(consCG, generalGrammar->getStartKind());
74
- cflChecker.check(generalGrammar, &cflGraphBuilder, graph);
75
- grammar = normalizer.normalize(generalGrammar);
76
- cflChecker.check(grammar, &cflGraphBuilder, graph);
77
- svfir->dump("SVFIR");
78
- grammar->dump();
79
- delete consCG;
80
- delete generalGrammar;
81
- }
82
- else
83
- {
84
- GrammarBase *generalGrammar = gReader.build();
85
- graph = cflGraphBuilder.buildFromDot(Options::InputFilename, generalGrammar);
86
- cflChecker.check(generalGrammar, &cflGraphBuilder, graph);
87
- grammar = normalizer.normalize(generalGrammar);
88
- cflChecker.check(grammar, &cflGraphBuilder, graph);
89
- delete generalGrammar;
90
- }
91
- solver = new CFLSolver(graph, grammar);
92
- solver->solve();
93
- if (Options::GraphIsFromDot == false)
94
- {
95
- PointerAnalysis::finalize();
96
- }
97
- }
58
+ virtual void analyze();
98
59
 
99
60
  /// Interface exposed to users of our pointer analysis, given Value infos
100
61
  virtual AliasResult alias(const Value* v1, const Value* v2)
@@ -28,20 +28,155 @@
28
28
  */
29
29
  #ifndef CFLGrammar_H_
30
30
  #define CFLGrammar_H_
31
- #include "Util/BasicTypes.h"
31
+ #include "Util/SVFBasicTypes.h"
32
32
 
33
33
  namespace SVF
34
34
  {
35
+
35
36
  class GrammarBase
36
37
  {
37
38
  public:
38
- typedef u32_t Symbol;
39
- typedef std::vector<Symbol> Production;
40
- typedef Set<Production> Productions;
41
- typedef u32_t Attribute;
42
39
  typedef u32_t Kind;
40
+ typedef u32_t Attribute;
41
+ typedef u32_t VariableAttribute;
42
+ typedef struct Symbol
43
+ {
44
+ Kind kind: 8;
45
+ Attribute attribute: 16;
46
+ VariableAttribute variableAttribute: 8;
47
+
48
+ /// Default Value for Symbol is 0.
49
+ Symbol() : kind(0), attribute(0), variableAttribute(0) {}
50
+
51
+ /// Contruct from u32_t move the bit to right field
52
+ Symbol(const u32_t& num) : kind(num & 0xFF), attribute((num >> 8 ) & 0xFFFF), variableAttribute((num >> 24)) {}
53
+
54
+ /// Conversion of u32_t
55
+ operator u32_t()
56
+ {
57
+ u32_t num = 0;
58
+ num += this->variableAttribute << 24;
59
+ num += this->attribute << 8;
60
+ num += this->kind;
61
+ return num;
62
+ }
63
+
64
+ /// Conversion of u64_t
65
+ operator u64_t()
66
+ {
67
+ u64_t num = 0;
68
+ num += this->variableAttribute << 24;
69
+ num += this->attribute << 8;
70
+ num += this->kind;
71
+ return num;
72
+ }
73
+
74
+ operator s64_t() const
75
+ {
76
+ s64_t num = 0;
77
+ num += this->variableAttribute << 24;
78
+ num += this->attribute << 8;
79
+ num += this->kind;
80
+ return num;
81
+ }
82
+
83
+ bool operator<(const Symbol& rhs)
84
+ {
85
+ return this->kind < rhs.kind;
86
+ }
87
+
88
+ void operator=(const int& i)
89
+ {
90
+ this->kind = EdgeKindMask & i;
91
+ this->attribute = i >> EdgeKindMaskBits;
92
+ this->variableAttribute = i >> AttributedKindMaskBits;
93
+ }
94
+
95
+ void operator=(unsigned long long num)
96
+ {
97
+ this->kind = num & 0xFF;
98
+ this->attribute = (num >> 8 ) & 0xFFFF;
99
+ this->variableAttribute = num >> 24;
100
+ }
101
+
102
+ void operator=(const Kind& kind)
103
+ {
104
+ this->kind = kind;
105
+ }
106
+
107
+ bool operator==(const Symbol& s)
108
+ {
109
+ return ((this->kind == s.kind) && (this->attribute == s.attribute) && (this->variableAttribute == s.variableAttribute));
110
+ }
111
+
112
+ bool operator==(const Symbol& s) const
113
+ {
114
+ return ((kind == s.kind) && (attribute == s.attribute) && (variableAttribute == s.variableAttribute));
115
+ }
116
+
117
+ bool operator!=(const Symbol& s) const
118
+ {
119
+ return ! (*this == s) ;
120
+ }
121
+
122
+
123
+ bool operator==(const int& i)
124
+ {
125
+ return ((this->kind == (EdgeKindMask & i)) && (this->attribute == (i >> EdgeKindMaskBits)) && (this->variableAttribute == (i >> AttributedKindMaskBits)));
126
+ }
127
+
128
+ bool operator==(const Kind& k) const
129
+ {
130
+ return (this->kind == k);
131
+ }
132
+
133
+ bool operator==(const Kind& k)
134
+ {
135
+ return (this->kind == k);
136
+ }
137
+ } Symbol;
138
+
139
+ class SymbolHash
140
+ {
141
+ public:
142
+ size_t operator()(const Symbol &s) const
143
+ {
144
+ std::hash<u32_t> h;
145
+ return h(u32_t(s));
146
+ }
147
+ };
148
+
43
149
 
44
- inline Map<std::string, Kind>& getNonterminals()
150
+ struct SymbolVectorHash
151
+ {
152
+ size_t operator()(const std::vector<Symbol> &v) const
153
+ {
154
+ size_t h = v.size();
155
+
156
+ SymbolHash hf;
157
+ for (const Symbol &t : v)
158
+ {
159
+ h ^= hf(t) + 0x9e3779b9 + (h << 6) + (h >> 2);
160
+ }
161
+
162
+ return h;
163
+ }
164
+ };
165
+
166
+ template<typename Key, typename Value, typename Hash = SymbolHash,
167
+ typename KeyEqual = std::equal_to<Key>,
168
+ typename Allocator = std::allocator<std::pair<const Key, Value>>>
169
+ using SymbolMap = std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>;
170
+
171
+ template <typename Key, typename Hash = SymbolVectorHash, typename KeyEqual = std::equal_to<Key>,
172
+ typename Allocator = std::allocator<Key>>
173
+ using SymbolSet = std::unordered_set<Key, Hash, KeyEqual, Allocator>;
174
+
175
+ typedef std::vector<Symbol> Production;
176
+ typedef SymbolSet<Production> Productions;
177
+
178
+
179
+ inline Map<std::string, Kind>& getNonterminals()
45
180
  {
46
181
  return this->nonterminals;
47
182
  }
@@ -61,7 +196,7 @@ public:
61
196
  this->terminals = terminals;
62
197
  }
63
198
 
64
- inline Map<Symbol, Productions>& getRawProductions()
199
+ inline SymbolMap<Symbol, Productions>& getRawProductions()
65
200
  {
66
201
  return this->rawProductions;
67
202
  }
@@ -91,7 +226,11 @@ public:
91
226
  this->totalKind = totalKind;
92
227
  }
93
228
 
94
- void setRawProductions(Map<Symbol, Productions>& rawProductions);
229
+ std::string extractKindStrFromSymbolStr(const std::string symbolStr) const;
230
+
231
+ std::string extractAttributeStrFromSymbolStr(const std::string symbolStr) const;
232
+
233
+ void setRawProductions(SymbolMap<Symbol, Productions>& rawProductions);
95
234
 
96
235
  void setKind2AttrsMap(const Map<Kind, Set<Attribute>>& kind2AttrsMap);
97
236
 
@@ -99,6 +238,8 @@ public:
99
238
 
100
239
  Kind str2Kind(std::string str) const;
101
240
 
241
+ Symbol str2Symbol(const std::string str) const;
242
+
102
243
  std::string kind2Str(Kind kind) const;
103
244
 
104
245
  std::string sym2StrDump(Symbol sym) const;
@@ -108,41 +249,46 @@ public:
108
249
  return prod.at(pos);
109
250
  }
110
251
 
111
- inline const Set<Symbol>& getAttrSyms() const
252
+ inline const Set<Kind>& getAttrSyms() const
112
253
  {
113
254
  return this->attributeKinds;
114
255
  }
115
256
 
257
+ /// Insert kind to nonterminal and return kind.
258
+ Kind insertNonterminalKind(std::string const kindStr);
259
+
260
+ /// From SymbolStr extract kind to inserted in nonterminal
261
+ /// symbolStr = <kindStr> [_] [ attributeStr | variableattributeStr ]
116
262
  Kind insertTerminalKind(std::string strLit);
117
- Kind insertNonTerminalKind(std::string strLit);
118
- void insertAttribute(Kind kind, Attribute a);
119
263
 
120
- inline static Kind getSymKind(Symbol sym)
121
- {
122
- return (EdgeKindMask & sym);
123
- }
264
+ Symbol insertSymbol(std::string strLit);
124
265
 
125
- inline static Attribute getSymAttribute(Symbol sym)
126
- {
127
- return (sym >> EdgeKindMaskBits);
128
- }
266
+ Symbol insertNonTerminalSymbol(std::string strLit);
267
+
268
+ void insertAttribute(Kind kind, Attribute a);
129
269
 
130
270
  inline static Kind getAttributedKind(Attribute attribute, Kind kind)
131
271
  {
132
272
  return ((attribute << EdgeKindMaskBits)| kind );
133
273
  }
134
274
 
275
+ inline static Kind getVariabledKind(VariableAttribute variableAttribute, Kind kind)
276
+ {
277
+ return ((variableAttribute << AttributedKindMaskBits) | kind);
278
+ }
279
+
135
280
  protected:
136
281
  static constexpr unsigned char EdgeKindMaskBits = 8; ///< We use the lower 8 bits to denote edge kind
282
+ static constexpr unsigned char AttributedKindMaskBits = 24; ///< We use the lower 24 bits to denote attributed kind
137
283
  static constexpr u64_t EdgeKindMask = (~0ULL) >> (64 - EdgeKindMaskBits);
138
284
  Kind startKind;
139
285
  private:
140
- Set<Kind> attributeKinds;
141
- Map<Kind, Set<Attribute>> kind2AttrsMap;
142
- Map<Symbol, Productions> rawProductions;
143
- Kind totalKind;
144
286
  Map<std::string, Kind> nonterminals;
145
287
  Map<std::string, Kind> terminals;
288
+ Set<Kind> attributeKinds;
289
+ Map<Kind, Set<Attribute>> kind2AttrsMap;
290
+ SymbolMap<Symbol, Productions> rawProductions;
291
+ u32_t totalKind;
146
292
  };
147
293
 
148
294
  class CFLGrammar : public GrammarBase
@@ -168,17 +314,17 @@ public:
168
314
  return epsilonProds;
169
315
  }
170
316
 
171
- Map<Symbol, Productions>& getSingleRHS2Prods()
317
+ SymbolMap<Symbol, Productions>& getSingleRHS2Prods()
172
318
  {
173
319
  return singleRHS2Prods;
174
320
  }
175
321
 
176
- Map<Symbol, Productions>& getFirstRHS2Prods()
322
+ SymbolMap<Symbol, Productions>& getFirstRHS2Prods()
177
323
  {
178
324
  return firstRHS2Prods;
179
325
  }
180
326
 
181
- Map<Symbol, Productions>& getSecondRHS2Prods()
327
+ SymbolMap<Symbol, Productions>& getSecondRHS2Prods()
182
328
  {
183
329
  return secondRHS2Prods;
184
330
  }
@@ -240,17 +386,86 @@ public:
240
386
 
241
387
  void dump() const;
242
388
 
389
+ void dump(std::string fileName) const;
390
+
391
+
243
392
  const inline int num_generator()
244
393
  {
245
394
  return newTerminalSubscript++;
246
395
  }
247
396
 
248
397
  private:
249
- Set<Production> epsilonProds;
250
- Map<Symbol, Productions> singleRHS2Prods;
251
- Map<Symbol, Productions> firstRHS2Prods;
252
- Map<Symbol, Productions> secondRHS2Prods;
253
- Symbol newTerminalSubscript;
398
+ SymbolSet<Production> epsilonProds;
399
+ SymbolMap<Symbol, Productions> singleRHS2Prods;
400
+ SymbolMap<Symbol, Productions> firstRHS2Prods;
401
+ SymbolMap<Symbol, Productions> secondRHS2Prods;
402
+ u32_t newTerminalSubscript;
403
+ };
404
+
405
+ /**
406
+ * Worklist with "first in first out" order.
407
+ * New nodes will be pushed at back and popped from front.
408
+ * Elements in the list are unique as they're recorded by Set.
409
+ */
410
+ template<class Data>
411
+ class CFLFIFOWorkList
412
+ {
413
+ typedef GrammarBase::SymbolSet<Data> DataSet;
414
+ typedef std::deque<Data> DataDeque;
415
+ public:
416
+ CFLFIFOWorkList() {}
417
+
418
+ ~CFLFIFOWorkList() {}
419
+
420
+ inline bool empty() const
421
+ {
422
+ return data_list.empty();
423
+ }
424
+
425
+ inline bool find(Data data) const
426
+ {
427
+ return (data_set.find(data) == data_set.end() ? false : true);
428
+ }
429
+
430
+ /**
431
+ * Push a data into the work list.
432
+ */
433
+ inline bool push(Data data)
434
+ {
435
+ if (data_set.find(data) == data_set.end())
436
+ {
437
+ data_list.push_back(data);
438
+ data_set.insert(data);
439
+ return true;
440
+ }
441
+ else
442
+ return false;
443
+ }
444
+
445
+ /**
446
+ * Pop a data from the END of work list.
447
+ */
448
+ inline Data pop()
449
+ {
450
+ assert(!empty() && "work list is empty");
451
+ Data data = data_list.front();
452
+ data_list.pop_front();
453
+ data_set.erase(data);
454
+ return data;
455
+ }
456
+
457
+ /*!
458
+ * Clear all the data
459
+ */
460
+ inline void clear()
461
+ {
462
+ data_list.clear();
463
+ data_set.clear();
464
+ }
465
+
466
+ private:
467
+ DataSet data_set; ///< store all data in the work list.
468
+ DataDeque data_list; ///< work list using std::vector.
254
469
  };
255
470
 
256
471
  }
@@ -1,19 +1,17 @@
1
1
  Start:
2
- V
2
+ V
3
+ Terminal:
4
+ Addr Copy Store Load Gep Vgep
3
5
  Productions:
4
- F -> Addr;
5
- F -> Addr ( Copy ) *;
6
- F -> Addr ( Store V Load ) *;
7
- F -> ( Copy ) *;
8
- F -> ( Store V Load ) *;
9
- Fbar -> Addrbar;
10
- Fbar -> Addrbar ( Copybar ) *;
11
- Fbar -> Addrbar ( Loadbar V Storebar ) *;
12
- Fbar -> ( Copybar ) *;
13
- Fbar -> ( Loadbar V Storebar ) *;
6
+ F -> epsilon;
7
+ F -> F Copy;
8
+ F -> F Store V Load;
9
+ Gepbar_j -> Vgepbar Fbar Gepbar_i;
10
+ Fbar -> epsilon;
11
+ Fbar -> Copybar Fbar;
12
+ Fbar -> Loadbar V Storebar Fbar;
14
13
  V -> Fbar V F;
15
- V -> Gepbar_i V Gep_i;
16
14
  V -> Addrbar Addr;
17
- V -> epsilon;
18
-
19
-
15
+ V -> Gepbar_i V Gep_i;
16
+ Gep_j -> Gep_i F Vgep;
17
+
@@ -39,14 +39,14 @@ namespace SVF
39
39
 
40
40
  class CFLGraphBuilder
41
41
  {
42
- private:
42
+ protected:
43
43
  typedef CFLGrammar::Kind Kind;
44
44
  typedef CFLGrammar::Symbol Symbol;
45
45
  Map<std::string, Kind> label2KindMap;
46
46
  Map<Kind, std::string> kind2LabelMap;
47
47
  Map<CFLGrammar::Kind, Set<CFLGrammar::Attribute>> kind2AttrsMap;
48
48
  bool externMap;
49
- Symbol current;
49
+ Kind current;
50
50
 
51
51
  public:
52
52
  /// add attribute to kind2Attribute Map
@@ -73,12 +73,22 @@ public:
73
73
 
74
74
  /// Build Bidirectional graph by copying nodes and edges from any graph inherited from GenericGraph
75
75
  template<class N, class E>
76
- CFLGraph* buildBigraph(GenericGraph<N,E>* graph, Kind startKind)
76
+ CFLGraph* buildBigraph(GenericGraph<N,E>* graph, Kind startKind, GrammarBase *grammar)
77
77
  {
78
78
  CFLGraph *cflGraph = new CFLGraph(startKind);
79
- Map<std::string, SVF::CFLGraph::Symbol> ConstMap = {{"Addr",0}, {"Copy", 1},{"Store", 2},{"Load", 3},{"Gep_i", 4},{"Vgep", 5},{"Addrbar",6}, {"Copybar", 7},{"Storebar", 8},{"Loadbar", 9},{"Gepbar_i", 10},{"Vgepbar", 11}};
80
79
  externMap = true;
81
- for(auto pairV : ConstMap)
80
+ for(auto pairV : grammar->getTerminals())
81
+ {
82
+ if(label2KindMap.find(pairV.first) == label2KindMap.end())
83
+ {
84
+ label2KindMap.insert(pairV);
85
+ }
86
+ if(kind2LabelMap.find(pairV.second) == kind2LabelMap.end())
87
+ {
88
+ kind2LabelMap.insert(make_pair(pairV.second, pairV.first));
89
+ }
90
+ }
91
+ for(auto pairV : grammar->getNonterminals())
82
92
  {
83
93
  if(label2KindMap.find(pairV.first) == label2KindMap.end())
84
94
  {
@@ -100,29 +110,10 @@ public:
100
110
  for(E* edge : node->getOutEdges())
101
111
  {
102
112
  CFLGrammar::Kind edgeLabel = edge->getEdgeKind();
103
- // Need to get the offset from the Const Edge
104
- // The offset present edge is only from Normal Gep CG at moment
105
- if(NormalGepCGEdge::classof(edge))
106
- {
107
- NormalGepCGEdge *nGepEdge = SVFUtil::dyn_cast<NormalGepCGEdge>(edge);
108
- CFLGrammar::Attribute attr = nGepEdge->getConstantFieldIdx();
109
- addAttribute(edgeLabel, attr);
110
- edgeLabel = CFLGrammar::getAttributedKind(attr, edgeLabel);
111
- cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
112
- std::string key = kind2LabelMap[edge->getEdgeKind()];
113
- key.pop_back();
114
- key.pop_back(); // _i standsfor attribute variable should place at last
115
- key.append("bar_i"); // for example Gep_i should be Gepbar_i, not Gep_ibar
116
- cflGraph->addCFLEdge(cflGraph->getGNode(edge->getDstID()), cflGraph->getGNode(edge->getSrcID()), CFLGrammar::getAttributedKind(attr, label2KindMap[key]));
117
- addAttribute(label2KindMap[key], attr);
118
- }
119
- else
120
- {
121
- cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
122
- std::string key = kind2LabelMap[edge->getEdgeKind()];
123
- key.append("bar");
124
- cflGraph->addCFLEdge(cflGraph->getGNode(edge->getDstID()), cflGraph->getGNode(edge->getSrcID()), label2KindMap[key]);
125
- }
113
+ cflGraph->addCFLEdge(cflGraph->getGNode(edge->getSrcID()), cflGraph->getGNode(edge->getDstID()), edgeLabel);
114
+ std::string key = kind2LabelMap[edge->getEdgeKind()];
115
+ key.append("bar");
116
+ cflGraph->addCFLEdge(cflGraph->getGNode(edge->getDstID()), cflGraph->getGNode(edge->getSrcID()), label2KindMap[key]);
126
117
  }
127
118
  }
128
119
  return cflGraph;
@@ -147,8 +138,15 @@ public:
147
138
  {
148
139
  return this->kind2AttrsMap;
149
140
  }
141
+ };
150
142
 
151
-
143
+ class AliasCFLGraphBuilder : public CFLGraphBuilder
144
+ {
145
+ public:
146
+ /// Build Bidirectional graph by copying nodes and edges from const graph inherited from GenericGraph
147
+ CFLGraph* buildBigraph(ConstraintGraph *graph, Kind startKind, GrammarBase *grammar);
152
148
  };
149
+
153
150
  }// SVF
154
151
 
152
+