Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
Line
Count
Source (jump to first uncovered line)
1
//===- ThreadSafetyTraverse.h ----------------------------------*- C++ --*-===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This file defines a framework for doing generic traversals and rewriting
11
// operations over the Thread Safety TIL.
12
//
13
// UNDER CONSTRUCTION.  USE AT YOUR OWN RISK.
14
//
15
//===----------------------------------------------------------------------===//
16
17
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
18
#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
19
20
#include "ThreadSafetyTIL.h"
21
#include <ostream>
22
23
namespace clang {
24
namespace threadSafety {
25
namespace til {
26
27
// Defines an interface used to traverse SExprs.  Traversals have been made as
28
// generic as possible, and are intended to handle any kind of pass over the
29
// AST, e.g. visiters, copying, non-destructive rewriting, destructive
30
// (in-place) rewriting, hashing, typing, etc.
31
//
32
// Traversals implement the functional notion of a "fold" operation on SExprs.
33
// Each SExpr class provides a traverse method, which does the following:
34
//   * e->traverse(v):
35
//       // compute a result r_i for each subexpression e_i
36
//       for (i = 1..n)  r_i = v.traverse(e_i);
37
//       // combine results into a result for e,  where X is the class of e
38
//       return v.reduceX(*e, r_1, .. r_n).
39
//
40
// A visitor can control the traversal by overriding the following methods:
41
//   * v.traverse(e):
42
//       return v.traverseByCase(e), which returns v.traverseX(e)
43
//   * v.traverseX(e):   (X is the class of e)
44
//       return e->traverse(v).
45
//   * v.reduceX(*e, r_1, .. r_n):
46
//       compute a result for a node of type X
47
//
48
// The reduceX methods control the kind of traversal (visitor, copy, etc.).
49
// They are defined in derived classes.
50
//
51
// Class R defines the basic interface types (R_SExpr).
52
template <class Self, class R>
53
class Traversal {
54
public:
55
  Self *self() { return static_cast<Self *>(this); }
56
57
  // Traverse an expression -- returning a result of type R_SExpr.
58
  // Override this method to do something for every expression, regardless
59
  // of which kind it is.
60
  // E is a reference, so this can be use for in-place updates.
61
  // The type T must be a subclass of SExpr.
62
  template <class T>
63
  typename R::R_SExpr traverse(T* &E, typename R::R_Ctx Ctx) {
64
    return traverseSExpr(E, Ctx);
65
  }
66
67
  // Override this method to do something for every expression.
68
  // Does not allow in-place updates.
69
  typename R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx) {
70
    return traverseByCase(E, Ctx);
71
  }
72
73
  // Helper method to call traverseX(e) on the appropriate type.
74
  typename R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx) {
75
    switch (E->opcode()) {
76
#define TIL_OPCODE_DEF(X)                                                   \
77
    case COP_##X:                                                           \
78
      return self()->traverse##X(cast<X>(E), Ctx);
79
#include "ThreadSafetyOps.def"
80
#undef TIL_OPCODE_DEF
81
    }
82
    return self()->reduceNull();
83
  }
84
85
// Traverse e, by static dispatch on the type "X" of e.
86
// Override these methods to do something for a particular kind of term.
87
#define TIL_OPCODE_DEF(X)                                                   \
88
  typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) {            \
89
    return e->traverse(*self(), Ctx);                                       \
90
  }
91
#include "ThreadSafetyOps.def"
92
#undef TIL_OPCODE_DEF
93
};
94
95
96
// Base class for simple reducers that don't much care about the context.
97
class SimpleReducerBase {
98
public:
99
  enum TraversalKind {
100
    TRV_Normal,   // ordinary subexpressions
101
    TRV_Decl,     // declarations (e.g. function bodies)
102
    TRV_Lazy,     // expressions that require lazy evaluation
103
    TRV_Type      // type expressions
104
  };
105
106
  // R_Ctx defines a "context" for the traversal, which encodes information
107
  // about where a term appears.  This can be used to encoding the
108
  // "current continuation" for CPS transforms, or other information.
109
  typedef TraversalKind R_Ctx;
110
111
  // Create context for an ordinary subexpression.
112
0
  R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; }
113
114
  // Create context for a subexpression that occurs in a declaration position
115
  // (e.g. function body).
116
0
  R_Ctx declCtx(R_Ctx Ctx) { return TRV_Decl; }
117
118
  // Create context for a subexpression that occurs in a position that
119
  // should be reduced lazily.  (e.g. code body).
120
0
  R_Ctx lazyCtx(R_Ctx Ctx) { return TRV_Lazy; }
121
122
  // Create context for a subexpression that occurs in a type position.
123
0
  R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; }
124
};
125
126
127
// Base class for traversals that rewrite an SExpr to another SExpr.
128
class CopyReducerBase : public SimpleReducerBase {
129
public:
130
  // R_SExpr is the result type for a traversal.
131
  // A copy or non-destructive rewrite returns a newly allocated term.
132
  typedef SExpr *R_SExpr;
133
  typedef BasicBlock *R_BasicBlock;
134
135
  // Container is a minimal interface used to store results when traversing
136
  // SExprs of variable arity, such as Phi, Goto, and SCFG.
137
  template <class T> class Container {
138
  public:
139
    // Allocate a new container with a capacity for n elements.
140
    Container(CopyReducerBase &S, unsigned N) : Elems(S.Arena, N) {}
141
142
    // Push a new element onto the container.
143
    void push_back(T E) { Elems.push_back(E); }
144
145
    SimpleArray<T> Elems;
146
  };
147
148
0
  CopyReducerBase(MemRegionRef A) : Arena(A) {}
149
150
protected:
151
  MemRegionRef Arena;
152
};
153
154
155
// Base class for visit traversals.
156
class VisitReducerBase : public SimpleReducerBase {
157
public:
158
  // A visitor returns a bool, representing success or failure.
159
  typedef bool R_SExpr;
160
  typedef bool R_BasicBlock;
161
162
  // A visitor "container" is a single bool, which accumulates success.
163
  template <class T> class Container {
164
  public:
165
    Container(VisitReducerBase &S, unsigned N) : Success(true) {}
166
    void push_back(bool E) { Success = Success && E; }
167
168
    bool Success;
169
  };
170
};
171
172
173
// Implements a traversal that visits each subexpression, and returns either
174
// true or false.
175
template <class Self>
176
class VisitReducer : public Traversal<Self, VisitReducerBase>,
177
                     public VisitReducerBase {
178
public:
179
  VisitReducer() {}
180
181
public:
182
  R_SExpr reduceNull() { return true; }
183
  R_SExpr reduceUndefined(Undefined &Orig) { return true; }
184
  R_SExpr reduceWildcard(Wildcard &Orig) { return true; }
185
186
  R_SExpr reduceLiteral(Literal &Orig) { return true; }
187
  template<class T>
188
  R_SExpr reduceLiteralT(LiteralT<T> &Orig) { return true; }
189
  R_SExpr reduceLiteralPtr(Literal &Orig) { return true; }
190
191
  R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
192
    return Nvd && E0;
193
  }
194
  R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
195
    return Nvd && E0;
196
  }
197
  R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
198
    return E0 && E1;
199
  }
200
  R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
201
    return E0 && E1;
202
  }
203
  R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
204
    return E0 && E1;
205
  }
206
  R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
207
    return E0 && E1;
208
  }
209
  R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; }
210
  R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; }
211
  R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
212
  R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
213
  R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
214
  R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) {
215
    return E0 && E1;
216
  }
217
  R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) {
218
    return E0 && E1;
219
  }
220
  R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
221
  R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
222
    return E0 && E1;
223
  }
224
  R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; }
225
226
  R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) {
227
    return Bbs.Success;
228
  }
229
  R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<R_SExpr> &As,
230
                                Container<R_SExpr> &Is, R_SExpr T) {
231
    return (As.Success && Is.Success && T);
232
  }
233
  R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
234
    return As.Success;
235
  }
236
  R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
237
    return true;
238
  }
239
  R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
240
    return C;
241
  }
242
  R_SExpr reduceReturn(Return &O, R_SExpr E) {
243
    return E;
244
  }
245
246
  R_SExpr reduceIdentifier(Identifier &Orig) {
247
    return true;
248
  }
249
  R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
250
    return C && T && E;
251
  }
252
  R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
253
    return Nvd && B;
254
  }
255
256
  Variable *enterScope(Variable &Orig, R_SExpr E0) { return &Orig; }
257
  void exitScope(const Variable &Orig) {}
258
  void enterCFG(SCFG &Cfg) {}
259
  void exitCFG(SCFG &Cfg) {}
260
  void enterBasicBlock(BasicBlock &BB) {}
261
  void exitBasicBlock(BasicBlock &BB) {}
262
263
  Variable   *reduceVariableRef  (Variable *Ovd)   { return Ovd; }
264
  BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
265
266
public:
267
  bool traverse(SExpr *E, TraversalKind K = TRV_Normal) {
268
    Success = Success && this->traverseByCase(E);
269
    return Success;
270
  }
271
272
  static bool visit(SExpr *E) {
273
    Self Visitor;
274
    return Visitor.traverse(E, TRV_Normal);
275
  }
276
277
private:
278
  bool Success;
279
};
280
281
282
// Basic class for comparison operations over expressions.
283
template <typename Self>
284
class Comparator {
285
protected:
286
22.0k
  Self *self() { return reinterpret_cast<Self *>(this); }
clang::threadSafety::til::Comparator<clang::threadSafety::til::MatchComparator>::self()
Line
Count
Source
286
19.9k
  Self *self() { return reinterpret_cast<Self *>(this); }
clang::threadSafety::til::Comparator<clang::threadSafety::til::EqualsComparator>::self()
Line
Count
Source
286
2.06k
  Self *self() { return reinterpret_cast<Self *>(this); }
287
288
public:
289
22.0k
  bool compareByCase(const SExpr *E1, const SExpr* E2) {
290
22.0k
    switch (E1->opcode()) {
291
22.0k
#define TIL_OPCODE_DEF(X)                                                     \
292
22.0k
    case COP_##X:                                                             \
293
22.0k
      return cast<X>(E1)->compare(cast<X>(E2), *self());
294
0
#include "ThreadSafetyOps.def"
295
22.0k
#undef TIL_OPCODE_DEF
296
22.0k
    }
297
0
    return false;
298
22.0k
  }
clang::threadSafety::til::Comparator<clang::threadSafety::til::MatchComparator>::compareByCase(clang::threadSafety::til::SExpr const*, clang::threadSafety::til::SExpr const*)
Line
Count
Source
289
19.9k
  bool compareByCase(const SExpr *E1, const SExpr* E2) {
290
19.9k
    switch (E1->opcode()) {
291
19.9k
#define TIL_OPCODE_DEF(X)                                                     \
292
19.9k
    case COP_##X:                                                             \
293
19.9k
      return cast<X>(E1)->compare(cast<X>(E2), *self());
294
0
#include "ThreadSafetyOps.def"
295
19.9k
#undef TIL_OPCODE_DEF
296
19.9k
    }
297
0
    return false;
298
19.9k
  }
clang::threadSafety::til::Comparator<clang::threadSafety::til::EqualsComparator>::compareByCase(clang::threadSafety::til::SExpr const*, clang::threadSafety::til::SExpr const*)
Line
Count
Source
289
2.06k
  bool compareByCase(const SExpr *E1, const SExpr* E2) {
290
2.06k
    switch (E1->opcode()) {
291
2.06k
#define TIL_OPCODE_DEF(X)                                                     \
292
2.06k
    case COP_##X:                                                             \
293
2.06k
      return cast<X>(E1)->compare(cast<X>(E2), *self());
294
0
#include "ThreadSafetyOps.def"
295
2.06k
#undef TIL_OPCODE_DEF
296
2.06k
    }
297
0
    return false;
298
2.06k
  }
299
};
300
301
302
class EqualsComparator : public Comparator<EqualsComparator> {
303
public:
304
  // Result type for the comparison, e.g. bool for simple equality,
305
  // or int for lexigraphic comparison (-1, 0, 1).  Must have one value which
306
  // denotes "true".
307
  typedef bool CType;
308
309
0
  CType trueResult() { return true; }
310
1.03k
  bool notTrue(CType ct) { return !ct; }
311
312
0
  bool compareIntegers(unsigned i, unsigned j)       { return i == j; }
313
0
  bool compareStrings (StringRef s, StringRef r)     { return s == r; }
314
1.12k
  bool comparePointers(const void* P, const void* Q) { return P == Q; }
315
316
2.08k
  bool compare(const SExpr *E1, const SExpr* E2) {
317
2.08k
    if (E1->opcode() != E2->opcode())
318
20
      return false;
319
2.06k
    return compareByCase(E1, E2);
320
2.08k
  }
321
322
  // TODO -- handle alpha-renaming of variables
323
0
  void enterScope(const Variable* V1, const Variable* V2) { }
324
0
  void leaveScope() { }
325
326
416
  bool compareVariableRefs(const Variable* V1, const Variable* V2) {
327
416
    return V1 == V2;
328
416
  }
329
330
542
  static bool compareExprs(const SExpr *E1, const SExpr* E2) {
331
542
    EqualsComparator Eq;
332
542
    return Eq.compare(E1, E2);
333
542
  }
334
};
335
336
337
338
class MatchComparator : public Comparator<MatchComparator> {
339
public:
340
  // Result type for the comparison, e.g. bool for simple equality,
341
  // or int for lexigraphic comparison (-1, 0, 1).  Must have one value which
342
  // denotes "true".
343
  typedef bool CType;
344
345
196
  CType trueResult() { return true; }
346
10.1k
  bool notTrue(CType ct) { return !ct; }
347
348
150
  bool compareIntegers(unsigned i, unsigned j)       { return i == j; }
349
0
  bool compareStrings (StringRef s, StringRef r)     { return s == r; }
350
8.05k
  bool comparePointers(const void* P, const void* Q) { return P == Q; }
351
352
20.7k
  bool compare(const SExpr *E1, const SExpr* E2) {
353
20.7k
    // Wildcards match anything.
354
20.7k
    if (
E1->opcode() == COP_Wildcard || 20.7k
E2->opcode() == COP_Wildcard20.7k
)
355
72
      return true;
356
20.7k
    // otherwise normal equality.
357
20.7k
    
if (20.7k
E1->opcode() != E2->opcode()20.7k
)
358
724
      return false;
359
19.9k
    return compareByCase(E1, E2);
360
20.7k
  }
361
362
  // TODO -- handle alpha-renaming of variables
363
0
  void enterScope(const Variable* V1, const Variable* V2) { }
364
0
  void leaveScope() { }
365
366
5.07k
  bool compareVariableRefs(const Variable* V1, const Variable* V2) {
367
5.07k
    return V1 == V2;
368
5.07k
  }
369
370
5.33k
  static bool compareExprs(const SExpr *E1, const SExpr* E2) {
371
5.33k
    MatchComparator Matcher;
372
5.33k
    return Matcher.compare(E1, E2);
373
5.33k
  }
374
};
375
376
377
378
// inline std::ostream& operator<<(std::ostream& SS, StringRef R) {
379
//   return SS.write(R.data(), R.size());
380
// }
381
382
// Pretty printer for TIL expressions
383
template <typename Self, typename StreamType>
384
class PrettyPrinter {
385
private:
386
  bool Verbose;  // Print out additional information
387
  bool Cleanup;  // Omit redundant decls.
388
  bool CStyle;   // Print exprs in C-like syntax.
389
390
public:
391
  PrettyPrinter(bool V = false, bool C = true, bool CS = true)
392
     : Verbose(V), Cleanup(C), CStyle(CS)
393
1.38k
  {}
394
395
1.38k
  static void print(const SExpr *E, StreamType &SS) {
396
1.38k
    Self printer;
397
1.38k
    printer.printSExpr(E, SS, Prec_MAX);
398
1.38k
  }
399
400
protected:
401
4.49k
  Self *self() { return reinterpret_cast<Self *>(this); }
402
403
0
  void newline(StreamType &SS) {
404
0
    SS << "\n";
405
0
  }
406
407
  // TODO: further distinguish between binary operations.
408
  static const unsigned Prec_Atom = 0;
409
  static const unsigned Prec_Postfix = 1;
410
  static const unsigned Prec_Unary = 2;
411
  static const unsigned Prec_Binary = 3;
412
  static const unsigned Prec_Other = 4;
413
  static const unsigned Prec_Decl = 5;
414
  static const unsigned Prec_MAX = 6;
415
416
  // Return the precedence of a given node, for use in pretty printing.
417
1.96k
  unsigned precedence(const SExpr *E) {
418
1.96k
    switch (E->opcode()) {
419
0
      case COP_Future:     return Prec_Atom;
420
0
      case COP_Undefined:  return Prec_Atom;
421
2
      case COP_Wildcard:   return Prec_Atom;
422
1.96k
423
6
      case COP_Literal:    return Prec_Atom;
424
411
      case COP_LiteralPtr: return Prec_Atom;
425
2
      case COP_Variable:   return Prec_Atom;
426
0
      case COP_Function:   return Prec_Decl;
427
0
      case COP_SFunction:  return Prec_Decl;
428
0
      case COP_Code:       return Prec_Decl;
429
0
      case COP_Field:      return Prec_Decl;
430
1.96k
431
0
      case COP_Apply:      return Prec_Postfix;
432
244
      case COP_SApply:     return Prec_Postfix;
433
1.25k
      case COP_Project:    return Prec_Postfix;
434
1.96k
435
18
      case COP_Call:       return Prec_Postfix;
436
0
      case COP_Alloc:      return Prec_Other;
437
0
      case COP_Load:       return Prec_Postfix;
438
0
      case COP_Store:      return Prec_Other;
439
8
      case COP_ArrayIndex: return Prec_Postfix;
440
0
      case COP_ArrayAdd:   return Prec_Postfix;
441
1.96k
442
0
      case COP_UnaryOp:    return Prec_Unary;
443
8
      case COP_BinaryOp:   return Prec_Binary;
444
6
      case COP_Cast:       return Prec_Atom;
445
1.96k
446
0
      case COP_SCFG:       return Prec_Decl;
447
0
      case COP_BasicBlock: return Prec_MAX;
448
0
      case COP_Phi:        return Prec_Atom;
449
0
      case COP_Goto:       return Prec_Atom;
450
0
      case COP_Branch:     return Prec_Atom;
451
0
      case COP_Return:     return Prec_Other;
452
1.96k
453
0
      case COP_Identifier: return Prec_Atom;
454
8
      case COP_IfThenElse: return Prec_Other;
455
0
      case COP_Let:        return Prec_Decl;
456
1.96k
    }
457
0
    return Prec_MAX;
458
1.96k
  }
459
460
0
  void printBlockLabel(StreamType & SS, const BasicBlock *BB, int index) {
461
0
    if (
!BB0
) {
462
0
      SS << "BB_null";
463
0
      return;
464
0
    }
465
0
    SS << "BB_";
466
0
    SS << BB->blockID();
467
0
    if (
index >= 00
) {
468
0
      SS << ":";
469
0
      SS << index;
470
0
    }
471
0
  }
472
473
474
1.96k
  void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) {
475
1.96k
    if (
!E1.96k
) {
476
0
      self()->printNull(SS);
477
0
      return;
478
0
    }
479
1.96k
    
if (1.96k
Sub && 1.96k
E->block()1.96k
&&
E->opcode() != COP_Variable0
) {
480
0
      SS << "_x" << E->id();
481
0
      return;
482
0
    }
483
1.96k
    
if (1.96k
self()->precedence(E) > P1.96k
) {
484
8
      // Wrap expr in () if necessary.
485
8
      SS << "(";
486
8
      self()->printSExpr(E, SS, Prec_MAX);
487
8
      SS << ")";
488
8
      return;
489
8
    }
490
1.96k
491
1.95k
    switch (E->opcode()) {
492
1.95k
#define TIL_OPCODE_DEF(X)                                                  \
493
1.95k
    case COP_##X:                                                          \
494
1.95k
      self()->print##X(cast<X>(E), SS);                                    \
495
1.95k
      return;
496
0
#include "ThreadSafetyOps.def"
497
1.96k
#undef TIL_OPCODE_DEF
498
1.96k
    }
499
1.96k
  }
500
501
0
  void printNull(StreamType &SS) {
502
0
    SS << "#null";
503
0
  }
504
505
0
  void printFuture(const Future *E, StreamType &SS) {
506
0
    self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
507
0
  }
508
509
0
  void printUndefined(const Undefined *E, StreamType &SS) {
510
0
    SS << "#undefined";
511
0
  }
512
513
2
  void printWildcard(const Wildcard *E, StreamType &SS) {
514
2
    SS << "*";
515
2
  }
516
517
  template<class T>
518
0
  void printLiteralT(const LiteralT<T> *E, StreamType &SS) {
519
0
    SS << E->value();
520
0
  }
Unexecuted instantiation: void clang::threadSafety::til::PrettyPrinter<clang::threadSafety::til::StdPrinter, std::__1::basic_ostream<char, std::__1::char_traits<char> > >::printLiteralT<unsigned int>(clang::threadSafety::til::LiteralT<unsigned int> const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&)
Unexecuted instantiation: void clang::threadSafety::til::PrettyPrinter<clang::threadSafety::til::StdPrinter, std::__1::basic_ostream<char, std::__1::char_traits<char> > >::printLiteralT<long long>(clang::threadSafety::til::LiteralT<long long> const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&)
Unexecuted instantiation: void clang::threadSafety::til::PrettyPrinter<clang::threadSafety::til::StdPrinter, std::__1::basic_ostream<char, std::__1::char_traits<char> > >::printLiteralT<unsigned long long>(clang::threadSafety::til::LiteralT<unsigned long long> const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&)
Unexecuted instantiation: void clang::threadSafety::til::PrettyPrinter<clang::threadSafety::til::StdPrinter, std::__1::basic_ostream<char, std::__1::char_traits<char> > >::printLiteralT<signed char>(clang::threadSafety::til::LiteralT<signed char> const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&)
Unexecuted instantiation: void clang::threadSafety::til::PrettyPrinter<clang::threadSafety::til::StdPrinter, std::__1::basic_ostream<char, std::__1::char_traits<char> > >::printLiteralT<double>(clang::threadSafety::til::LiteralT<double> const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&)
Unexecuted instantiation: void clang::threadSafety::til::PrettyPrinter<clang::threadSafety::til::StdPrinter, std::__1::basic_ostream<char, std::__1::char_traits<char> > >::printLiteralT<llvm::StringRef>(clang::threadSafety::til::LiteralT<llvm::StringRef> const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&)
Unexecuted instantiation: void clang::threadSafety::til::PrettyPrinter<clang::threadSafety::til::StdPrinter, std::__1::basic_ostream<char, std::__1::char_traits<char> > >::printLiteralT<int>(clang::threadSafety::til::LiteralT<int> const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&)
Unexecuted instantiation: void clang::threadSafety::til::PrettyPrinter<clang::threadSafety::til::StdPrinter, std::__1::basic_ostream<char, std::__1::char_traits<char> > >::printLiteralT<unsigned short>(clang::threadSafety::til::LiteralT<unsigned short> const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&)
Unexecuted instantiation: void clang::threadSafety::til::PrettyPrinter<clang::threadSafety::til::StdPrinter, std::__1::basic_ostream<char, std::__1::char_traits<char> > >::printLiteralT<short>(clang::threadSafety::til::LiteralT<short> const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&)
Unexecuted instantiation: void clang::threadSafety::til::PrettyPrinter<clang::threadSafety::til::StdPrinter, std::__1::basic_ostream<char, std::__1::char_traits<char> > >::printLiteralT<float>(clang::threadSafety::til::LiteralT<float> const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&)
521
522
0
  void printLiteralT(const LiteralT<uint8_t> *E, StreamType &SS) {
523
0
    SS << "'" << E->value() << "'";
524
0
  }
525
526
6
  void printLiteral(const Literal *E, StreamType &SS) {
527
6
    if (
E->clangExpr()6
) {
528
6
      SS << getSourceLiteralString(E->clangExpr());
529
6
      return;
530
6
    }
531
0
    else {
532
0
      ValueType VT = E->valueType();
533
0
      switch (VT.Base) {
534
0
      case ValueType::BT_Void: {
535
0
        SS << "void";
536
0
        return;
537
0
      }
538
0
      case ValueType::BT_Bool: {
539
0
        if (E->as<bool>().value())
540
0
          SS << "true";
541
0
        else
542
0
          SS << "false";
543
0
        return;
544
0
      }
545
0
      case ValueType::BT_Int: {
546
0
        switch (VT.Size) {
547
0
        case ValueType::ST_8:
548
0
          if (VT.Signed)
549
0
            printLiteralT(&E->as<int8_t>(), SS);
550
0
          else
551
0
            printLiteralT(&E->as<uint8_t>(), SS);
552
0
          return;
553
0
        case ValueType::ST_16:
554
0
          if (VT.Signed)
555
0
            printLiteralT(&E->as<int16_t>(), SS);
556
0
          else
557
0
            printLiteralT(&E->as<uint16_t>(), SS);
558
0
          return;
559
0
        case ValueType::ST_32:
560
0
          if (VT.Signed)
561
0
            printLiteralT(&E->as<int32_t>(), SS);
562
0
          else
563
0
            printLiteralT(&E->as<uint32_t>(), SS);
564
0
          return;
565
0
        case ValueType::ST_64:
566
0
          if (VT.Signed)
567
0
            printLiteralT(&E->as<int64_t>(), SS);
568
0
          else
569
0
            printLiteralT(&E->as<uint64_t>(), SS);
570
0
          return;
571
0
        default:
572
0
          break;
573
0
        }
574
0
        break;
575
0
      }
576
0
      case ValueType::BT_Float: {
577
0
        switch (VT.Size) {
578
0
        case ValueType::ST_32:
579
0
          printLiteralT(&E->as<float>(), SS);
580
0
          return;
581
0
        case ValueType::ST_64:
582
0
          printLiteralT(&E->as<double>(), SS);
583
0
          return;
584
0
        default:
585
0
          break;
586
0
        }
587
0
        break;
588
0
      }
589
0
      case ValueType::BT_String: {
590
0
        SS << "\"";
591
0
        printLiteralT(&E->as<StringRef>(), SS);
592
0
        SS << "\"";
593
0
        return;
594
0
      }
595
0
      case ValueType::BT_Pointer: {
596
0
        SS << "#ptr";
597
0
        return;
598
0
      }
599
0
      case ValueType::BT_ValueRef: {
600
0
        SS << "#vref";
601
0
        return;
602
0
      }
603
0
      }
604
0
    }
605
0
    SS << "#lit";
606
0
  }
607
608
411
  void printLiteralPtr(const LiteralPtr *E, StreamType &SS) {
609
411
    SS << E->clangDecl()->getNameAsString();
610
411
  }
611
612
2
  void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false) {
613
2
    if (
CStyle && 2
V->kind() == Variable::VK_SFun2
)
614
2
      SS << "this";
615
2
    else
616
0
      SS << V->name() << V->id();
617
2
  }
618
619
0
  void printFunction(const Function *E, StreamType &SS, unsigned sugared = 0) {
620
0
    switch (sugared) {
621
0
      default:
622
0
        SS << "\\(";   // Lambda
623
0
        break;
624
0
      case 1:
625
0
        SS << "(";     // Slot declarations
626
0
        break;
627
0
      case 2:
628
0
        SS << ", ";    // Curried functions
629
0
        break;
630
0
    }
631
0
    self()->printVariable(E->variableDecl(), SS, true);
632
0
    SS << ": ";
633
0
    self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
634
0
635
0
    const SExpr *B = E->body();
636
0
    if (
B && 0
B->opcode() == COP_Function0
)
637
0
      self()->printFunction(cast<Function>(B), SS, 2);
638
0
    else {
639
0
      SS << ")";
640
0
      self()->printSExpr(B, SS, Prec_Decl);
641
0
    }
642
0
  }
643
644
0
  void printSFunction(const SFunction *E, StreamType &SS) {
645
0
    SS << "@";
646
0
    self()->printVariable(E->variableDecl(), SS, true);
647
0
    SS << " ";
648
0
    self()->printSExpr(E->body(), SS, Prec_Decl);
649
0
  }
650
651
0
  void printCode(const Code *E, StreamType &SS) {
652
0
    SS << ": ";
653
0
    self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
654
0
    SS << " -> ";
655
0
    self()->printSExpr(E->body(), SS, Prec_Decl);
656
0
  }
657
658
0
  void printField(const Field *E, StreamType &SS) {
659
0
    SS << ": ";
660
0
    self()->printSExpr(E->range(), SS, Prec_Decl-1);
661
0
    SS << " = ";
662
0
    self()->printSExpr(E->body(), SS, Prec_Decl);
663
0
  }
664
665
20
  void printApply(const Apply *E, StreamType &SS, bool sugared = false) {
666
20
    const SExpr *F = E->fun();
667
20
    if (
F->opcode() == COP_Apply20
) {
668
8
      printApply(cast<Apply>(F), SS, true);
669
8
      SS << ", ";
670
20
    } else {
671
12
      self()->printSExpr(F, SS, Prec_Postfix);
672
12
      SS << "(";
673
12
    }
674
20
    self()->printSExpr(E->arg(), SS, Prec_MAX);
675
20
    if (!sugared)
676
0
      SS << ")$";
677
20
  }
678
679
244
  void printSApply(const SApply *E, StreamType &SS) {
680
244
    self()->printSExpr(E->sfun(), SS, Prec_Postfix);
681
244
    if (
E->isDelegation()244
) {
682
0
      SS << "@(";
683
0
      self()->printSExpr(E->arg(), SS, Prec_MAX);
684
0
      SS << ")";
685
0
    }
686
244
  }
687
688
1.25k
  void printProject(const Project *E, StreamType &SS) {
689
1.25k
    if (
CStyle1.25k
) {
690
1.25k
      // Omit the  this->
691
1.25k
      if (const SApply *
SAP1.25k
= dyn_cast<SApply>(E->record())) {
692
1.24k
        if (const Variable *
V1.24k
= dyn_cast<Variable>(SAP->sfun())) {
693
997
          if (
!SAP->isDelegation() && 997
V->kind() == Variable::VK_SFun997
) {
694
997
            SS << E->slotName();
695
997
            return;
696
997
          }
697
997
        }
698
1.24k
      }
699
254
      
if (254
isa<Wildcard>(E->record())254
) {
700
10
        // handle existentials
701
10
        SS << "&";
702
10
        SS << E->clangDecl()->getQualifiedNameAsString();
703
10
        return;
704
10
      }
705
1.25k
    }
706
244
    self()->printSExpr(E->record(), SS, Prec_Postfix);
707
244
    if (
CStyle && 244
E->isArrow()244
) {
708
90
      SS << "->";
709
90
    }
710
154
    else {
711
154
      SS << ".";
712
154
    }
713
1.25k
    SS << E->slotName();
714
1.25k
  }
715
716
18
  void printCall(const Call *E, StreamType &SS) {
717
18
    const SExpr *T = E->target();
718
18
    if (
T->opcode() == COP_Apply18
) {
719
12
      self()->printApply(cast<Apply>(T), SS, true);
720
12
      SS << ")";
721
12
    }
722
6
    else {
723
6
      self()->printSExpr(T, SS, Prec_Postfix);
724
6
      SS << "()";
725
6
    }
726
18
  }
727
728
0
  void printAlloc(const Alloc *E, StreamType &SS) {
729
0
    SS << "new ";
730
0
    self()->printSExpr(E->dataType(), SS, Prec_Other-1);
731
0
  }
732
733
0
  void printLoad(const Load *E, StreamType &SS) {
734
0
    self()->printSExpr(E->pointer(), SS, Prec_Postfix);
735
0
    if (!CStyle)
736
0
      SS << "^";
737
0
  }
738
739
0
  void printStore(const Store *E, StreamType &SS) {
740
0
    self()->printSExpr(E->destination(), SS, Prec_Other-1);
741
0
    SS << " := ";
742
0
    self()->printSExpr(E->source(), SS, Prec_Other-1);
743
0
  }
744
745
8
  void printArrayIndex(const ArrayIndex *E, StreamType &SS) {
746
8
    self()->printSExpr(E->array(), SS, Prec_Postfix);
747
8
    SS << "[";
748
8
    self()->printSExpr(E->index(), SS, Prec_MAX);
749
8
    SS << "]";
750
8
  }
751
752
0
  void printArrayAdd(const ArrayAdd *E, StreamType &SS) {
753
0
    self()->printSExpr(E->array(), SS, Prec_Postfix);
754
0
    SS << " + ";
755
0
    self()->printSExpr(E->index(), SS, Prec_Atom);
756
0
  }
757
758
0
  void printUnaryOp(const UnaryOp *E, StreamType &SS) {
759
0
    SS << getUnaryOpcodeString(E->unaryOpcode());
760
0
    self()->printSExpr(E->expr(), SS, Prec_Unary);
761
0
  }
762
763
4
  void printBinaryOp(const BinaryOp *E, StreamType &SS) {
764
4
    self()->printSExpr(E->expr0(), SS, Prec_Binary-1);
765
4
    SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " ";
766
4
    self()->printSExpr(E->expr1(), SS, Prec_Binary-1);
767
4
  }
768
769
6
  void printCast(const Cast *E, StreamType &SS) {
770
6
    if (
!CStyle6
) {
771
0
      SS << "cast[";
772
0
      SS << E->castOpcode();
773
0
      SS << "](";
774
0
      self()->printSExpr(E->expr(), SS, Prec_Unary);
775
0
      SS << ")";
776
0
      return;
777
0
    }
778
6
    self()->printSExpr(E->expr(), SS, Prec_Unary);
779
6
  }
780
781
0
  void printSCFG(const SCFG *E, StreamType &SS) {
782
0
    SS << "CFG {\n";
783
0
    for (auto BBI : *E) {
784
0
      printBasicBlock(BBI, SS);
785
0
    }
786
0
    SS << "}";
787
0
    newline(SS);
788
0
  }
789
790
791
0
  void printBBInstr(const SExpr *E, StreamType &SS) {
792
0
    bool Sub = false;
793
0
    if (
E->opcode() == COP_Variable0
) {
794
0
      auto *V = cast<Variable>(E);
795
0
      SS << "let " << V->name() << V->id() << " = ";
796
0
      E = V->definition();
797
0
      Sub = true;
798
0
    }
799
0
    else 
if (0
E->opcode() != COP_Store0
) {
800
0
      SS << "let _x" << E->id() << " = ";
801
0
    }
802
0
    self()->printSExpr(E, SS, Prec_MAX, Sub);
803
0
    SS << ";";
804
0
    newline(SS);
805
0
  }
806
807
0
  void printBasicBlock(const BasicBlock *E, StreamType &SS) {
808
0
    SS << "BB_" << E->blockID() << ":";
809
0
    if (E->parent())
810
0
      SS << " BB_" << E->parent()->blockID();
811
0
    newline(SS);
812
0
813
0
    for (auto *A : E->arguments())
814
0
      printBBInstr(A, SS);
815
0
816
0
    for (auto *I : E->instructions())
817
0
      printBBInstr(I, SS);
818
0
819
0
    const SExpr *T = E->terminator();
820
0
    if (
T0
) {
821
0
      self()->printSExpr(T, SS, Prec_MAX, false);
822
0
      SS << ";";
823
0
      newline(SS);
824
0
    }
825
0
    newline(SS);
826
0
  }
827
828
0
  void printPhi(const Phi *E, StreamType &SS) {
829
0
    SS << "phi(";
830
0
    if (E->status() == Phi::PH_SingleVal)
831
0
      self()->printSExpr(E->values()[0], SS, Prec_MAX);
832
0
    else {
833
0
      unsigned i = 0;
834
0
      for (auto V : E->values()) {
835
0
        if (i++ > 0)
836
0
          SS << ", ";
837
0
        self()->printSExpr(V, SS, Prec_MAX);
838
0
      }
839
0
    }
840
0
    SS << ")";
841
0
  }
842
843
0
  void printGoto(const Goto *E, StreamType &SS) {
844
0
    SS << "goto ";
845
0
    printBlockLabel(SS, E->targetBlock(), E->index());
846
0
  }
847
848
0
  void printBranch(const Branch *E, StreamType &SS) {
849
0
    SS << "branch (";
850
0
    self()->printSExpr(E->condition(), SS, Prec_MAX);
851
0
    SS << ") ";
852
0
    printBlockLabel(SS, E->thenBlock(), -1);
853
0
    SS << " ";
854
0
    printBlockLabel(SS, E->elseBlock(), -1);
855
0
  }
856
857
0
  void printReturn(const Return *E, StreamType &SS) {
858
0
    SS << "return ";
859
0
    self()->printSExpr(E->returnValue(), SS, Prec_Other);
860
0
  }
861
862
0
  void printIdentifier(const Identifier *E, StreamType &SS) {
863
0
    SS << E->name();
864
0
  }
865
866
4
  void printIfThenElse(const IfThenElse *E, StreamType &SS) {
867
4
    if (
CStyle4
) {
868
4
      printSExpr(E->condition(), SS, Prec_Unary);
869
4
      SS << " ? ";
870
4
      printSExpr(E->thenExpr(), SS, Prec_Unary);
871
4
      SS << " : ";
872
4
      printSExpr(E->elseExpr(), SS, Prec_Unary);
873
4
      return;
874
4
    }
875
0
    SS << "if (";
876
0
    printSExpr(E->condition(), SS, Prec_MAX);
877
0
    SS << ") then ";
878
0
    printSExpr(E->thenExpr(), SS, Prec_Other);
879
0
    SS << " else ";
880
0
    printSExpr(E->elseExpr(), SS, Prec_Other);
881
0
  }
882
883
0
  void printLet(const Let *E, StreamType &SS) {
884
0
    SS << "let ";
885
0
    printVariable(E->variableDecl(), SS, true);
886
0
    SS << " = ";
887
0
    printSExpr(E->variableDecl()->definition(), SS, Prec_Decl-1);
888
0
    SS << "; ";
889
0
    printSExpr(E->body(), SS, Prec_Decl-1);
890
0
  }
891
};
892
893
894
class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> { };
895
896
897
898
} // end namespace til
899
} // end namespace threadSafety
900
} // end namespace clang
901
902
#endif  // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H