diff options
Diffstat (limited to 'include/clang/Analysis/Analyses/ThreadSafetyTraverse.h')
-rw-r--r-- | include/clang/Analysis/Analyses/ThreadSafetyTraverse.h | 450 |
1 files changed, 208 insertions, 242 deletions
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h index bc1490b..705fe91 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h @@ -14,10 +14,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H -#define LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H #include "ThreadSafetyTIL.h" +#include <ostream> namespace clang { namespace threadSafety { @@ -56,11 +57,16 @@ public: // Traverse an expression -- returning a result of type R_SExpr. // Override this method to do something for every expression, regardless // of which kind it is. - typename R::R_SExpr traverse(SExprRef &E, typename R::R_Ctx Ctx) { - return traverse(E.get(), Ctx); + // E is a reference, so this can be use for in-place updates. + // The type T must be a subclass of SExpr. + template <class T> + typename R::R_SExpr traverse(T* &E, typename R::R_Ctx Ctx) { + return traverseSExpr(E, Ctx); } - typename R::R_SExpr traverse(SExpr *E, typename R::R_Ctx Ctx) { + // Override this method to do something for every expression. + // Does not allow in-place updates. + typename R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx) { return traverseByCase(E, Ctx); } @@ -73,6 +79,7 @@ public: #include "ThreadSafetyOps.def" #undef TIL_OPCODE_DEF } + return self()->reduceNull(); } // Traverse e, by static dispatch on the type "X" of e. @@ -90,10 +97,10 @@ public: class SimpleReducerBase { public: enum TraversalKind { - TRV_Normal, - TRV_Decl, - TRV_Lazy, - TRV_Type + TRV_Normal, // ordinary subexpressions + TRV_Decl, // declarations (e.g. function bodies) + TRV_Lazy, // expressions that require lazy evaluation + TRV_Type // type expressions }; // R_Ctx defines a "context" for the traversal, which encodes information @@ -145,153 +152,6 @@ protected: }; -// Implements a traversal that makes a deep copy of an SExpr. -// The default behavior of reduce##X(...) is to create a copy of the original. -// Subclasses can override reduce##X to implement non-destructive rewriting -// passes. -template<class Self> -class CopyReducer : public Traversal<Self, CopyReducerBase>, - public CopyReducerBase { -public: - CopyReducer(MemRegionRef A) : CopyReducerBase(A) {} - -public: - R_SExpr reduceNull() { - return nullptr; - } - // R_SExpr reduceFuture(...) is never used. - - R_SExpr reduceUndefined(Undefined &Orig) { - return new (Arena) Undefined(Orig); - } - R_SExpr reduceWildcard(Wildcard &Orig) { - return new (Arena) Wildcard(Orig); - } - - R_SExpr reduceLiteral(Literal &Orig) { - return new (Arena) Literal(Orig); - } - template<class T> - R_SExpr reduceLiteralT(LiteralT<T> &Orig) { - return new (Arena) LiteralT<T>(Orig); - } - R_SExpr reduceLiteralPtr(LiteralPtr &Orig) { - return new (Arena) LiteralPtr(Orig); - } - - R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) { - return new (Arena) Function(Orig, Nvd, E0); - } - R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) { - return new (Arena) SFunction(Orig, Nvd, E0); - } - R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) Code(Orig, E0, E1); - } - R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) Field(Orig, E0, E1); - } - - R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) Apply(Orig, E0, E1); - } - R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) SApply(Orig, E0, E1); - } - R_SExpr reduceProject(Project &Orig, R_SExpr E0) { - return new (Arena) Project(Orig, E0); - } - R_SExpr reduceCall(Call &Orig, R_SExpr E0) { - return new (Arena) Call(Orig, E0); - } - - R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { - return new (Arena) Alloc(Orig, E0); - } - R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { - return new (Arena) Load(Orig, E0); - } - R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) Store(Orig, E0, E1); - } - R_SExpr reduceArrayIndex(ArrayIndex &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) ArrayIndex(Orig, E0, E1); - } - R_SExpr reduceArrayAdd(ArrayAdd &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) ArrayAdd(Orig, E0, E1); - } - R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { - return new (Arena) UnaryOp(Orig, E0); - } - R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) BinaryOp(Orig, E0, E1); - } - R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { - return new (Arena) Cast(Orig, E0); - } - - R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> &Bbs) { - return nullptr; // FIXME: implement CFG rewriting - } - R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As, - Container<Variable *> &Is, R_SExpr T) { - return nullptr; // FIXME: implement CFG rewriting - } - R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) { - return new (Arena) Phi(Orig, std::move(As.Elems)); - } - R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) { - return new (Arena) Goto(Orig, B, 0); // FIXME: set index - } - R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) { - return new (Arena) Branch(O, C, B0, B1, 0, 0); // FIXME: set indices - } - - R_SExpr reduceIdentifier(Identifier &Orig) { - return new (Arena) Identifier(Orig); - } - R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) { - return new (Arena) IfThenElse(Orig, C, T, E); - } - R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) { - return new (Arena) Let(Orig, Nvd, B); - } - - // Create a new variable from orig, and push it onto the lexical scope. - Variable *enterScope(Variable &Orig, R_SExpr E0) { - return new (Arena) Variable(Orig, E0); - } - // Exit the lexical scope of orig. - void exitScope(const Variable &Orig) {} - - void enterCFG(SCFG &Cfg) {} - void exitCFG(SCFG &Cfg) {} - void enterBasicBlock(BasicBlock &BB) {} - void exitBasicBlock(BasicBlock &BB) {} - - // Map Variable references to their rewritten definitions. - Variable *reduceVariableRef(Variable *Ovd) { return Ovd; } - - // Map BasicBlock references to their rewritten definitions. - BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; } -}; - - -class SExprCopier : public CopyReducer<SExprCopier> { -public: - typedef SExpr *R_SExpr; - - SExprCopier(MemRegionRef A) : CopyReducer(A) { } - - // Create a copy of e in region a. - static SExpr *copy(SExpr *E, MemRegionRef A) { - SExprCopier Copier(A); - return Copier.traverse(E, TRV_Normal); - } -}; - - - // Base class for visit traversals. class VisitReducerBase : public SimpleReducerBase { public: @@ -366,8 +226,8 @@ public: R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) { return Bbs.Success; } - R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As, - Container<Variable *> &Is, R_SExpr T) { + R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<R_SExpr> &As, + Container<R_SExpr> &Is, R_SExpr T) { return (As.Success && Is.Success && T); } R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) { @@ -379,6 +239,9 @@ public: R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) { return C; } + R_SExpr reduceReturn(Return &O, R_SExpr E) { + return E; + } R_SExpr reduceIdentifier(Identifier &Orig) { return true; @@ -423,7 +286,7 @@ protected: Self *self() { return reinterpret_cast<Self *>(this); } public: - bool compareByCase(SExpr *E1, SExpr* E2) { + bool compareByCase(const SExpr *E1, const SExpr* E2) { switch (E1->opcode()) { #define TIL_OPCODE_DEF(X) \ case COP_##X: \ @@ -431,6 +294,7 @@ public: #include "ThreadSafetyOps.def" #undef TIL_OPCODE_DEF } + return false; } }; @@ -449,38 +313,86 @@ public: bool compareStrings (StringRef s, StringRef r) { return s == r; } bool comparePointers(const void* P, const void* Q) { return P == Q; } - bool compare(SExpr *E1, SExpr* E2) { + bool compare(const SExpr *E1, const SExpr* E2) { if (E1->opcode() != E2->opcode()) return false; return compareByCase(E1, E2); } // TODO -- handle alpha-renaming of variables - void enterScope(Variable* V1, Variable* V2) { } + void enterScope(const Variable* V1, const Variable* V2) { } void leaveScope() { } - bool compareVariableRefs(Variable* V1, Variable* V2) { + bool compareVariableRefs(const Variable* V1, const Variable* V2) { return V1 == V2; } - static bool compareExprs(SExpr *E1, SExpr* E2) { + static bool compareExprs(const SExpr *E1, const SExpr* E2) { EqualsComparator Eq; return Eq.compare(E1, E2); } }; + +class MatchComparator : public Comparator<MatchComparator> { +public: + // Result type for the comparison, e.g. bool for simple equality, + // or int for lexigraphic comparison (-1, 0, 1). Must have one value which + // denotes "true". + typedef bool CType; + + CType trueResult() { return true; } + bool notTrue(CType ct) { return !ct; } + + bool compareIntegers(unsigned i, unsigned j) { return i == j; } + bool compareStrings (StringRef s, StringRef r) { return s == r; } + bool comparePointers(const void* P, const void* Q) { return P == Q; } + + bool compare(const SExpr *E1, const SExpr* E2) { + // Wildcards match anything. + if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard) + return true; + // otherwise normal equality. + if (E1->opcode() != E2->opcode()) + return false; + return compareByCase(E1, E2); + } + + // TODO -- handle alpha-renaming of variables + void enterScope(const Variable* V1, const Variable* V2) { } + void leaveScope() { } + + bool compareVariableRefs(const Variable* V1, const Variable* V2) { + return V1 == V2; + } + + static bool compareExprs(const SExpr *E1, const SExpr* E2) { + MatchComparator Matcher; + return Matcher.compare(E1, E2); + } +}; + + + +// inline std::ostream& operator<<(std::ostream& SS, StringRef R) { +// return SS.write(R.data(), R.size()); +// } + // Pretty printer for TIL expressions template <typename Self, typename StreamType> class PrettyPrinter { private: bool Verbose; // Print out additional information bool Cleanup; // Omit redundant decls. + bool CStyle; // Print exprs in C-like syntax. public: - PrettyPrinter(bool V = false, bool C = true) : Verbose(V), Cleanup(C) { } + PrettyPrinter(bool V = false, bool C = true, bool CS = true) + : Verbose(V), Cleanup(C), CStyle(CS) + {} - static void print(SExpr *E, StreamType &SS) { + static void print(const SExpr *E, StreamType &SS) { Self printer; printer.printSExpr(E, SS, Prec_MAX); } @@ -502,7 +414,7 @@ protected: static const unsigned Prec_MAX = 6; // Return the precedence of a given node, for use in pretty printing. - unsigned precedence(SExpr *E) { + unsigned precedence(const SExpr *E) { switch (E->opcode()) { case COP_Future: return Prec_Atom; case COP_Undefined: return Prec_Atom; @@ -529,13 +441,14 @@ protected: case COP_UnaryOp: return Prec_Unary; case COP_BinaryOp: return Prec_Binary; - case COP_Cast: return Prec_Unary; + case COP_Cast: return Prec_Atom; case COP_SCFG: return Prec_Decl; case COP_BasicBlock: return Prec_MAX; case COP_Phi: return Prec_Atom; case COP_Goto: return Prec_Atom; case COP_Branch: return Prec_Atom; + case COP_Return: return Prec_Other; case COP_Identifier: return Prec_Atom; case COP_IfThenElse: return Prec_Other; @@ -544,22 +457,29 @@ protected: return Prec_MAX; } - void printBlockLabel(StreamType & SS, BasicBlock *BB, unsigned index) { + void printBlockLabel(StreamType & SS, const BasicBlock *BB, int index) { if (!BB) { SS << "BB_null"; return; } SS << "BB_"; SS << BB->blockID(); - SS << ":"; - SS << index; + if (index >= 0) { + SS << ":"; + SS << index; + } } - void printSExpr(SExpr *E, StreamType &SS, unsigned P) { + + void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) { if (!E) { self()->printNull(SS); return; } + if (Sub && E->block() && E->opcode() != COP_Variable) { + SS << "_x" << E->id(); + return; + } if (self()->precedence(E) > P) { // Wrap expr in () if necessary. SS << "("; @@ -582,28 +502,28 @@ protected: SS << "#null"; } - void printFuture(Future *E, StreamType &SS) { + void printFuture(const Future *E, StreamType &SS) { self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom); } - void printUndefined(Undefined *E, StreamType &SS) { + void printUndefined(const Undefined *E, StreamType &SS) { SS << "#undefined"; } - void printWildcard(Wildcard *E, StreamType &SS) { - SS << "_"; + void printWildcard(const Wildcard *E, StreamType &SS) { + SS << "*"; } template<class T> - void printLiteralT(LiteralT<T> *E, StreamType &SS) { + void printLiteralT(const LiteralT<T> *E, StreamType &SS) { SS << E->value(); } - void printLiteralT(LiteralT<uint8_t> *E, StreamType &SS) { + void printLiteralT(const LiteralT<uint8_t> *E, StreamType &SS) { SS << "'" << E->value() << "'"; } - void printLiteral(Literal *E, StreamType &SS) { + void printLiteral(const Literal *E, StreamType &SS) { if (E->clangExpr()) { SS << getSourceLiteralString(E->clangExpr()); return; @@ -685,25 +605,18 @@ protected: SS << "#lit"; } - void printLiteralPtr(LiteralPtr *E, StreamType &SS) { + void printLiteralPtr(const LiteralPtr *E, StreamType &SS) { SS << E->clangDecl()->getNameAsString(); } - void printVariable(Variable *V, StreamType &SS, bool IsVarDecl = false) { - if (!IsVarDecl && Cleanup) { - SExpr* E = getCanonicalVal(V); - if (E != V) { - printSExpr(E, SS, Prec_Atom); - return; - } - } - if (V->kind() == Variable::VK_LetBB) - SS << V->name() << V->getBlockID() << "_" << V->getID(); + void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false) { + if (CStyle && V->kind() == Variable::VK_SFun) + SS << "this"; else - SS << V->name() << V->getID(); + SS << V->name() << V->id(); } - void printFunction(Function *E, StreamType &SS, unsigned sugared = 0) { + void printFunction(const Function *E, StreamType &SS, unsigned sugared = 0) { switch (sugared) { default: SS << "\\("; // Lambda @@ -719,7 +632,7 @@ protected: SS << ": "; self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX); - SExpr *B = E->body(); + const SExpr *B = E->body(); if (B && B->opcode() == COP_Function) self()->printFunction(cast<Function>(B), SS, 2); else { @@ -728,29 +641,29 @@ protected: } } - void printSFunction(SFunction *E, StreamType &SS) { + void printSFunction(const SFunction *E, StreamType &SS) { SS << "@"; self()->printVariable(E->variableDecl(), SS, true); SS << " "; self()->printSExpr(E->body(), SS, Prec_Decl); } - void printCode(Code *E, StreamType &SS) { + void printCode(const Code *E, StreamType &SS) { SS << ": "; self()->printSExpr(E->returnType(), SS, Prec_Decl-1); SS << " -> "; self()->printSExpr(E->body(), SS, Prec_Decl); } - void printField(Field *E, StreamType &SS) { + void printField(const Field *E, StreamType &SS) { SS << ": "; self()->printSExpr(E->range(), SS, Prec_Decl-1); SS << " = "; self()->printSExpr(E->body(), SS, Prec_Decl); } - void printApply(Apply *E, StreamType &SS, bool sugared = false) { - SExpr *F = E->fun(); + void printApply(const Apply *E, StreamType &SS, bool sugared = false) { + const SExpr *F = E->fun(); if (F->opcode() == COP_Apply) { printApply(cast<Apply>(F), SS, true); SS << ", "; @@ -763,7 +676,7 @@ protected: SS << ")$"; } - void printSApply(SApply *E, StreamType &SS) { + void printSApply(const SApply *E, StreamType &SS) { self()->printSExpr(E->sfun(), SS, Prec_Postfix); if (E->isDelegation()) { SS << "@("; @@ -772,14 +685,36 @@ protected: } } - void printProject(Project *E, StreamType &SS) { + void printProject(const Project *E, StreamType &SS) { + if (CStyle) { + // Omit the this-> + if (const SApply *SAP = dyn_cast<SApply>(E->record())) { + if (const Variable *V = dyn_cast<Variable>(SAP->sfun())) { + if (!SAP->isDelegation() && V->kind() == Variable::VK_SFun) { + SS << E->slotName(); + return; + } + } + } + if (isa<Wildcard>(E->record())) { + // handle existentials + SS << "&"; + SS << E->clangDecl()->getQualifiedNameAsString(); + return; + } + } self()->printSExpr(E->record(), SS, Prec_Postfix); - SS << "."; + if (CStyle && E->isArrow()) { + SS << "->"; + } + else { + SS << "."; + } SS << E->slotName(); } - void printCall(Call *E, StreamType &SS) { - SExpr *T = E->target(); + void printCall(const Call *E, StreamType &SS) { + const SExpr *T = E->target(); if (T->opcode() == COP_Apply) { self()->printApply(cast<Apply>(T), SS, true); SS << ")"; @@ -790,52 +725,60 @@ protected: } } - void printAlloc(Alloc *E, StreamType &SS) { + void printAlloc(const Alloc *E, StreamType &SS) { SS << "new "; self()->printSExpr(E->dataType(), SS, Prec_Other-1); } - void printLoad(Load *E, StreamType &SS) { + void printLoad(const Load *E, StreamType &SS) { self()->printSExpr(E->pointer(), SS, Prec_Postfix); - SS << "^"; + if (!CStyle) + SS << "^"; } - void printStore(Store *E, StreamType &SS) { + void printStore(const Store *E, StreamType &SS) { self()->printSExpr(E->destination(), SS, Prec_Other-1); SS << " := "; self()->printSExpr(E->source(), SS, Prec_Other-1); } - void printArrayIndex(ArrayIndex *E, StreamType &SS) { + void printArrayIndex(const ArrayIndex *E, StreamType &SS) { self()->printSExpr(E->array(), SS, Prec_Postfix); SS << "["; self()->printSExpr(E->index(), SS, Prec_MAX); SS << "]"; } - void printArrayAdd(ArrayAdd *E, StreamType &SS) { + void printArrayAdd(const ArrayAdd *E, StreamType &SS) { self()->printSExpr(E->array(), SS, Prec_Postfix); SS << " + "; self()->printSExpr(E->index(), SS, Prec_Atom); } - void printUnaryOp(UnaryOp *E, StreamType &SS) { + void printUnaryOp(const UnaryOp *E, StreamType &SS) { SS << getUnaryOpcodeString(E->unaryOpcode()); self()->printSExpr(E->expr(), SS, Prec_Unary); } - void printBinaryOp(BinaryOp *E, StreamType &SS) { + void printBinaryOp(const BinaryOp *E, StreamType &SS) { self()->printSExpr(E->expr0(), SS, Prec_Binary-1); SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " "; self()->printSExpr(E->expr1(), SS, Prec_Binary-1); } - void printCast(Cast *E, StreamType &SS) { - SS << "%"; + void printCast(const Cast *E, StreamType &SS) { + if (!CStyle) { + SS << "cast["; + SS << E->castOpcode(); + SS << "]("; + self()->printSExpr(E->expr(), SS, Prec_Unary); + SS << ")"; + return; + } self()->printSExpr(E->expr(), SS, Prec_Unary); } - void printSCFG(SCFG *E, StreamType &SS) { + void printSCFG(const SCFG *E, StreamType &SS) { SS << "CFG {\n"; for (auto BBI : *E) { printBasicBlock(BBI, SS); @@ -844,39 +787,45 @@ protected: newline(SS); } - void printBasicBlock(BasicBlock *E, StreamType &SS) { + + void printBBInstr(const SExpr *E, StreamType &SS) { + bool Sub = false; + if (E->opcode() == COP_Variable) { + auto *V = cast<Variable>(E); + SS << "let " << V->name() << V->id() << " = "; + E = V->definition(); + Sub = true; + } + else if (E->opcode() != COP_Store) { + SS << "let _x" << E->id() << " = "; + } + self()->printSExpr(E, SS, Prec_MAX, Sub); + SS << ";"; + newline(SS); + } + + void printBasicBlock(const BasicBlock *E, StreamType &SS) { SS << "BB_" << E->blockID() << ":"; if (E->parent()) SS << " BB_" << E->parent()->blockID(); newline(SS); - for (auto *A : E->arguments()) { - SS << "let "; - self()->printVariable(A, SS, true); - SS << " = "; - self()->printSExpr(A->definition(), SS, Prec_MAX); - SS << ";"; - newline(SS); - } - for (auto *I : E->instructions()) { - if (I->definition()->opcode() != COP_Store) { - SS << "let "; - self()->printVariable(I, SS, true); - SS << " = "; - } - self()->printSExpr(I->definition(), SS, Prec_MAX); - SS << ";"; - newline(SS); - } - SExpr *T = E->terminator(); + + for (auto *A : E->arguments()) + printBBInstr(A, SS); + + for (auto *I : E->instructions()) + printBBInstr(I, SS); + + const SExpr *T = E->terminator(); if (T) { - self()->printSExpr(T, SS, Prec_MAX); + self()->printSExpr(T, SS, Prec_MAX, false); SS << ";"; newline(SS); } newline(SS); } - void printPhi(Phi *E, StreamType &SS) { + void printPhi(const Phi *E, StreamType &SS) { SS << "phi("; if (E->status() == Phi::PH_SingleVal) self()->printSExpr(E->values()[0], SS, Prec_MAX); @@ -891,25 +840,38 @@ protected: SS << ")"; } - void printGoto(Goto *E, StreamType &SS) { + void printGoto(const Goto *E, StreamType &SS) { SS << "goto "; printBlockLabel(SS, E->targetBlock(), E->index()); } - void printBranch(Branch *E, StreamType &SS) { + void printBranch(const Branch *E, StreamType &SS) { SS << "branch ("; self()->printSExpr(E->condition(), SS, Prec_MAX); SS << ") "; - printBlockLabel(SS, E->thenBlock(), E->thenIndex()); + printBlockLabel(SS, E->thenBlock(), -1); SS << " "; - printBlockLabel(SS, E->elseBlock(), E->elseIndex()); + printBlockLabel(SS, E->elseBlock(), -1); } - void printIdentifier(Identifier *E, StreamType &SS) { + void printReturn(const Return *E, StreamType &SS) { + SS << "return "; + self()->printSExpr(E->returnValue(), SS, Prec_Other); + } + + void printIdentifier(const Identifier *E, StreamType &SS) { SS << E->name(); } - void printIfThenElse(IfThenElse *E, StreamType &SS) { + void printIfThenElse(const IfThenElse *E, StreamType &SS) { + if (CStyle) { + printSExpr(E->condition(), SS, Prec_Unary); + SS << " ? "; + printSExpr(E->thenExpr(), SS, Prec_Unary); + SS << " : "; + printSExpr(E->elseExpr(), SS, Prec_Unary); + return; + } SS << "if ("; printSExpr(E->condition(), SS, Prec_MAX); SS << ") then "; @@ -918,7 +880,7 @@ protected: printSExpr(E->elseExpr(), SS, Prec_Other); } - void printLet(Let *E, StreamType &SS) { + void printLet(const Let *E, StreamType &SS) { SS << "let "; printVariable(E->variableDecl(), SS, true); SS << " = "; @@ -929,6 +891,10 @@ protected: }; +class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> { }; + + + } // end namespace til } // end namespace threadSafety } // end namespace clang |