clang API Documentation
00001 //===- ThreadSafetyCommon.h ------------------------------------*- C++ --*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Parts of thread safety analysis that are not specific to thread safety 00011 // itself have been factored into classes here, where they can be potentially 00012 // used by other analyses. Currently these include: 00013 // 00014 // * Generalize clang CFG visitors. 00015 // * Conversion of the clang CFG to SSA form. 00016 // * Translation of clang Exprs to TIL SExprs 00017 // 00018 // UNDER CONSTRUCTION. USE AT YOUR OWN RISK. 00019 // 00020 //===----------------------------------------------------------------------===// 00021 00022 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H 00023 #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H 00024 00025 #include "clang/Analysis/Analyses/PostOrderCFGView.h" 00026 #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" 00027 #include "clang/Analysis/Analyses/ThreadSafetyTraverse.h" 00028 #include "clang/Analysis/AnalysisContext.h" 00029 #include "clang/Basic/OperatorKinds.h" 00030 00031 #include <memory> 00032 #include <ostream> 00033 #include <sstream> 00034 #include <vector> 00035 00036 00037 namespace clang { 00038 namespace threadSafety { 00039 00040 00041 // Various helper functions on til::SExpr 00042 namespace sx { 00043 00044 inline bool equals(const til::SExpr *E1, const til::SExpr *E2) { 00045 return til::EqualsComparator::compareExprs(E1, E2); 00046 } 00047 00048 inline bool matches(const til::SExpr *E1, const til::SExpr *E2) { 00049 // We treat a top-level wildcard as the "univsersal" lock. 00050 // It matches everything for the purpose of checking locks, but not 00051 // for unlocking them. 00052 if (isa<til::Wildcard>(E1)) 00053 return isa<til::Wildcard>(E2); 00054 if (isa<til::Wildcard>(E2)) 00055 return isa<til::Wildcard>(E1); 00056 00057 return til::MatchComparator::compareExprs(E1, E2); 00058 } 00059 00060 inline bool partiallyMatches(const til::SExpr *E1, const til::SExpr *E2) { 00061 const auto *PE1 = dyn_cast_or_null<til::Project>(E1); 00062 if (!PE1) 00063 return false; 00064 const auto *PE2 = dyn_cast_or_null<til::Project>(E2); 00065 if (!PE2) 00066 return false; 00067 return PE1->clangDecl() == PE2->clangDecl(); 00068 } 00069 00070 inline std::string toString(const til::SExpr *E) { 00071 std::stringstream ss; 00072 til::StdPrinter::print(E, ss); 00073 return ss.str(); 00074 } 00075 00076 } // end namespace sx 00077 00078 00079 00080 // This class defines the interface of a clang CFG Visitor. 00081 // CFGWalker will invoke the following methods. 00082 // Note that methods are not virtual; the visitor is templatized. 00083 class CFGVisitor { 00084 // Enter the CFG for Decl D, and perform any initial setup operations. 00085 void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First) {} 00086 00087 // Enter a CFGBlock. 00088 void enterCFGBlock(const CFGBlock *B) {} 00089 00090 // Returns true if this visitor implements handlePredecessor 00091 bool visitPredecessors() { return true; } 00092 00093 // Process a predecessor edge. 00094 void handlePredecessor(const CFGBlock *Pred) {} 00095 00096 // Process a successor back edge to a previously visited block. 00097 void handlePredecessorBackEdge(const CFGBlock *Pred) {} 00098 00099 // Called just before processing statements. 00100 void enterCFGBlockBody(const CFGBlock *B) {} 00101 00102 // Process an ordinary statement. 00103 void handleStatement(const Stmt *S) {} 00104 00105 // Process a destructor call 00106 void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD) {} 00107 00108 // Called after all statements have been handled. 00109 void exitCFGBlockBody(const CFGBlock *B) {} 00110 00111 // Return true 00112 bool visitSuccessors() { return true; } 00113 00114 // Process a successor edge. 00115 void handleSuccessor(const CFGBlock *Succ) {} 00116 00117 // Process a successor back edge to a previously visited block. 00118 void handleSuccessorBackEdge(const CFGBlock *Succ) {} 00119 00120 // Leave a CFGBlock. 00121 void exitCFGBlock(const CFGBlock *B) {} 00122 00123 // Leave the CFG, and perform any final cleanup operations. 00124 void exitCFG(const CFGBlock *Last) {} 00125 }; 00126 00127 00128 // Walks the clang CFG, and invokes methods on a given CFGVisitor. 00129 class CFGWalker { 00130 public: 00131 CFGWalker() : CFGraph(nullptr), ACtx(nullptr), SortedGraph(nullptr) {} 00132 00133 // Initialize the CFGWalker. This setup only needs to be done once, even 00134 // if there are multiple passes over the CFG. 00135 bool init(AnalysisDeclContext &AC) { 00136 ACtx = &AC; 00137 CFGraph = AC.getCFG(); 00138 if (!CFGraph) 00139 return false; 00140 00141 // Ignore anonymous functions. 00142 if (!dyn_cast_or_null<NamedDecl>(AC.getDecl())) 00143 return false; 00144 00145 SortedGraph = AC.getAnalysis<PostOrderCFGView>(); 00146 if (!SortedGraph) 00147 return false; 00148 00149 return true; 00150 } 00151 00152 // Traverse the CFG, calling methods on V as appropriate. 00153 template <class Visitor> 00154 void walk(Visitor &V) { 00155 PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph); 00156 00157 V.enterCFG(CFGraph, getDecl(), &CFGraph->getEntry()); 00158 00159 for (const auto *CurrBlock : *SortedGraph) { 00160 VisitedBlocks.insert(CurrBlock); 00161 00162 V.enterCFGBlock(CurrBlock); 00163 00164 // Process predecessors, handling back edges last 00165 if (V.visitPredecessors()) { 00166 SmallVector<CFGBlock*, 4> BackEdges; 00167 // Process successors 00168 for (CFGBlock::const_pred_iterator SI = CurrBlock->pred_begin(), 00169 SE = CurrBlock->pred_end(); 00170 SI != SE; ++SI) { 00171 if (*SI == nullptr) 00172 continue; 00173 00174 if (!VisitedBlocks.alreadySet(*SI)) { 00175 BackEdges.push_back(*SI); 00176 continue; 00177 } 00178 V.handlePredecessor(*SI); 00179 } 00180 00181 for (auto *Blk : BackEdges) 00182 V.handlePredecessorBackEdge(Blk); 00183 } 00184 00185 V.enterCFGBlockBody(CurrBlock); 00186 00187 // Process statements 00188 for (const auto &BI : *CurrBlock) { 00189 switch (BI.getKind()) { 00190 case CFGElement::Statement: { 00191 V.handleStatement(BI.castAs<CFGStmt>().getStmt()); 00192 break; 00193 } 00194 case CFGElement::AutomaticObjectDtor: { 00195 CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>(); 00196 CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>( 00197 AD.getDestructorDecl(ACtx->getASTContext())); 00198 VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl()); 00199 V.handleDestructorCall(VD, DD); 00200 break; 00201 } 00202 default: 00203 break; 00204 } 00205 } 00206 00207 V.exitCFGBlockBody(CurrBlock); 00208 00209 // Process successors, handling back edges first. 00210 if (V.visitSuccessors()) { 00211 SmallVector<CFGBlock*, 8> ForwardEdges; 00212 00213 // Process successors 00214 for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(), 00215 SE = CurrBlock->succ_end(); 00216 SI != SE; ++SI) { 00217 if (*SI == nullptr) 00218 continue; 00219 00220 if (!VisitedBlocks.alreadySet(*SI)) { 00221 ForwardEdges.push_back(*SI); 00222 continue; 00223 } 00224 V.handleSuccessorBackEdge(*SI); 00225 } 00226 00227 for (auto *Blk : ForwardEdges) 00228 V.handleSuccessor(Blk); 00229 } 00230 00231 V.exitCFGBlock(CurrBlock); 00232 } 00233 V.exitCFG(&CFGraph->getExit()); 00234 } 00235 00236 const CFG *getGraph() const { return CFGraph; } 00237 CFG *getGraph() { return CFGraph; } 00238 00239 const NamedDecl *getDecl() const { 00240 return dyn_cast<NamedDecl>(ACtx->getDecl()); 00241 } 00242 00243 const PostOrderCFGView *getSortedGraph() const { return SortedGraph; } 00244 00245 private: 00246 CFG *CFGraph; 00247 AnalysisDeclContext *ACtx; 00248 PostOrderCFGView *SortedGraph; 00249 }; 00250 00251 00252 00253 00254 class CapabilityExpr { 00255 // TODO: move this back into ThreadSafety.cpp 00256 // This is specific to thread safety. It is here because 00257 // translateAttrExpr needs it, but that should be moved too. 00258 00259 private: 00260 const til::SExpr* CapExpr; ///< The capability expression. 00261 bool Negated; ///< True if this is a negative capability 00262 00263 public: 00264 CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {} 00265 00266 const til::SExpr* sexpr() const { return CapExpr; } 00267 bool negative() const { return Negated; } 00268 00269 CapabilityExpr operator!() const { 00270 return CapabilityExpr(CapExpr, !Negated); 00271 } 00272 00273 bool equals(const CapabilityExpr &other) const { 00274 return (Negated == other.Negated) && sx::equals(CapExpr, other.CapExpr); 00275 } 00276 00277 bool matches(const CapabilityExpr &other) const { 00278 return (Negated == other.Negated) && sx::matches(CapExpr, other.CapExpr); 00279 } 00280 00281 bool matchesUniv(const CapabilityExpr &CapE) const { 00282 return isUniversal() || matches(CapE); 00283 } 00284 00285 bool partiallyMatches(const CapabilityExpr &other) const { 00286 return (Negated == other.Negated) && 00287 sx::partiallyMatches(CapExpr, other.CapExpr); 00288 } 00289 00290 std::string toString() const { 00291 if (Negated) 00292 return "!" + sx::toString(CapExpr); 00293 return sx::toString(CapExpr); 00294 } 00295 00296 bool shouldIgnore() const { return CapExpr == nullptr; } 00297 00298 bool isInvalid() const { return sexpr() && isa<til::Undefined>(sexpr()); } 00299 00300 bool isUniversal() const { return sexpr() && isa<til::Wildcard>(sexpr()); } 00301 }; 00302 00303 00304 00305 // Translate clang::Expr to til::SExpr. 00306 class SExprBuilder { 00307 public: 00308 /// \brief Encapsulates the lexical context of a function call. The lexical 00309 /// context includes the arguments to the call, including the implicit object 00310 /// argument. When an attribute containing a mutex expression is attached to 00311 /// a method, the expression may refer to formal parameters of the method. 00312 /// Actual arguments must be substituted for formal parameters to derive 00313 /// the appropriate mutex expression in the lexical context where the function 00314 /// is called. PrevCtx holds the context in which the arguments themselves 00315 /// should be evaluated; multiple calling contexts can be chained together 00316 /// by the lock_returned attribute. 00317 struct CallingContext { 00318 CallingContext *Prev; // The previous context; or 0 if none. 00319 const NamedDecl *AttrDecl; // The decl to which the attr is attached. 00320 const Expr *SelfArg; // Implicit object argument -- e.g. 'this' 00321 unsigned NumArgs; // Number of funArgs 00322 const Expr *const *FunArgs; // Function arguments 00323 bool SelfArrow; // is Self referred to with -> or .? 00324 00325 CallingContext(CallingContext *P, const NamedDecl *D = nullptr) 00326 : Prev(P), AttrDecl(D), SelfArg(nullptr), 00327 NumArgs(0), FunArgs(nullptr), SelfArrow(false) 00328 {} 00329 }; 00330 00331 SExprBuilder(til::MemRegionRef A) 00332 : Arena(A), SelfVar(nullptr), Scfg(nullptr), CurrentBB(nullptr), 00333 CurrentBlockInfo(nullptr) { 00334 // FIXME: we don't always have a self-variable. 00335 SelfVar = new (Arena) til::Variable(nullptr); 00336 SelfVar->setKind(til::Variable::VK_SFun); 00337 } 00338 00339 // Translate a clang expression in an attribute to a til::SExpr. 00340 // Constructs the context from D, DeclExp, and SelfDecl. 00341 CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D, 00342 const Expr *DeclExp, VarDecl *SelfD=nullptr); 00343 00344 CapabilityExpr translateAttrExpr(const Expr *AttrExp, CallingContext *Ctx); 00345 00346 // Translate a clang statement or expression to a TIL expression. 00347 // Also performs substitution of variables; Ctx provides the context. 00348 // Dispatches on the type of S. 00349 til::SExpr *translate(const Stmt *S, CallingContext *Ctx); 00350 til::SCFG *buildCFG(CFGWalker &Walker); 00351 00352 til::SExpr *lookupStmt(const Stmt *S); 00353 00354 til::BasicBlock *lookupBlock(const CFGBlock *B) { 00355 return BlockMap[B->getBlockID()]; 00356 } 00357 00358 const til::SCFG *getCFG() const { return Scfg; } 00359 til::SCFG *getCFG() { return Scfg; } 00360 00361 private: 00362 til::SExpr *translateDeclRefExpr(const DeclRefExpr *DRE, 00363 CallingContext *Ctx) ; 00364 til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx); 00365 til::SExpr *translateMemberExpr(const MemberExpr *ME, CallingContext *Ctx); 00366 til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx, 00367 const Expr *SelfE = nullptr); 00368 til::SExpr *translateCXXMemberCallExpr(const CXXMemberCallExpr *ME, 00369 CallingContext *Ctx); 00370 til::SExpr *translateCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE, 00371 CallingContext *Ctx); 00372 til::SExpr *translateUnaryOperator(const UnaryOperator *UO, 00373 CallingContext *Ctx); 00374 til::SExpr *translateBinOp(til::TIL_BinaryOpcode Op, 00375 const BinaryOperator *BO, 00376 CallingContext *Ctx, bool Reverse = false); 00377 til::SExpr *translateBinAssign(til::TIL_BinaryOpcode Op, 00378 const BinaryOperator *BO, 00379 CallingContext *Ctx, bool Assign = false); 00380 til::SExpr *translateBinaryOperator(const BinaryOperator *BO, 00381 CallingContext *Ctx); 00382 til::SExpr *translateCastExpr(const CastExpr *CE, CallingContext *Ctx); 00383 til::SExpr *translateArraySubscriptExpr(const ArraySubscriptExpr *E, 00384 CallingContext *Ctx); 00385 til::SExpr *translateAbstractConditionalOperator( 00386 const AbstractConditionalOperator *C, CallingContext *Ctx); 00387 00388 til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx); 00389 00390 // Map from statements in the clang CFG to SExprs in the til::SCFG. 00391 typedef llvm::DenseMap<const Stmt*, til::SExpr*> StatementMap; 00392 00393 // Map from clang local variables to indices in a LVarDefinitionMap. 00394 typedef llvm::DenseMap<const ValueDecl *, unsigned> LVarIndexMap; 00395 00396 // Map from local variable indices to SSA variables (or constants). 00397 typedef std::pair<const ValueDecl *, til::SExpr *> NameVarPair; 00398 typedef CopyOnWriteVector<NameVarPair> LVarDefinitionMap; 00399 00400 struct BlockInfo { 00401 LVarDefinitionMap ExitMap; 00402 bool HasBackEdges; 00403 unsigned UnprocessedSuccessors; // Successors yet to be processed 00404 unsigned ProcessedPredecessors; // Predecessors already processed 00405 00406 BlockInfo() 00407 : HasBackEdges(false), UnprocessedSuccessors(0), 00408 ProcessedPredecessors(0) {} 00409 BlockInfo(BlockInfo &&RHS) 00410 : ExitMap(std::move(RHS.ExitMap)), 00411 HasBackEdges(RHS.HasBackEdges), 00412 UnprocessedSuccessors(RHS.UnprocessedSuccessors), 00413 ProcessedPredecessors(RHS.ProcessedPredecessors) {} 00414 00415 BlockInfo &operator=(BlockInfo &&RHS) { 00416 if (this != &RHS) { 00417 ExitMap = std::move(RHS.ExitMap); 00418 HasBackEdges = RHS.HasBackEdges; 00419 UnprocessedSuccessors = RHS.UnprocessedSuccessors; 00420 ProcessedPredecessors = RHS.ProcessedPredecessors; 00421 } 00422 return *this; 00423 } 00424 00425 private: 00426 BlockInfo(const BlockInfo &) LLVM_DELETED_FUNCTION; 00427 void operator=(const BlockInfo &) LLVM_DELETED_FUNCTION; 00428 }; 00429 00430 // We implement the CFGVisitor API 00431 friend class CFGWalker; 00432 00433 void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First); 00434 void enterCFGBlock(const CFGBlock *B); 00435 bool visitPredecessors() { return true; } 00436 void handlePredecessor(const CFGBlock *Pred); 00437 void handlePredecessorBackEdge(const CFGBlock *Pred); 00438 void enterCFGBlockBody(const CFGBlock *B); 00439 void handleStatement(const Stmt *S); 00440 void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD); 00441 void exitCFGBlockBody(const CFGBlock *B); 00442 bool visitSuccessors() { return true; } 00443 void handleSuccessor(const CFGBlock *Succ); 00444 void handleSuccessorBackEdge(const CFGBlock *Succ); 00445 void exitCFGBlock(const CFGBlock *B); 00446 void exitCFG(const CFGBlock *Last); 00447 00448 void insertStmt(const Stmt *S, til::SExpr *E) { 00449 SMap.insert(std::make_pair(S, E)); 00450 } 00451 til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD); 00452 00453 til::SExpr *addStatement(til::SExpr *E, const Stmt *S, 00454 const ValueDecl *VD = nullptr); 00455 til::SExpr *lookupVarDecl(const ValueDecl *VD); 00456 til::SExpr *addVarDecl(const ValueDecl *VD, til::SExpr *E); 00457 til::SExpr *updateVarDecl(const ValueDecl *VD, til::SExpr *E); 00458 00459 void makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E); 00460 void mergeEntryMap(LVarDefinitionMap Map); 00461 void mergeEntryMapBackEdge(); 00462 void mergePhiNodesBackEdge(const CFGBlock *Blk); 00463 00464 private: 00465 // Set to true when parsing capability expressions, which get translated 00466 // inaccurately in order to hack around smart pointers etc. 00467 static const bool CapabilityExprMode = true; 00468 00469 til::MemRegionRef Arena; 00470 til::Variable *SelfVar; // Variable to use for 'this'. May be null. 00471 00472 til::SCFG *Scfg; 00473 StatementMap SMap; // Map from Stmt to TIL Variables 00474 LVarIndexMap LVarIdxMap; // Indices of clang local vars. 00475 std::vector<til::BasicBlock *> BlockMap; // Map from clang to til BBs. 00476 std::vector<BlockInfo> BBInfo; // Extra information per BB. 00477 // Indexed by clang BlockID. 00478 00479 LVarDefinitionMap CurrentLVarMap; 00480 std::vector<til::Phi*> CurrentArguments; 00481 std::vector<til::SExpr*> CurrentInstructions; 00482 std::vector<til::Phi*> IncompleteArgs; 00483 til::BasicBlock *CurrentBB; 00484 BlockInfo *CurrentBlockInfo; 00485 }; 00486 00487 00488 // Dump an SCFG to llvm::errs(). 00489 void printSCFG(CFGWalker &Walker); 00490 00491 00492 } // end namespace threadSafety 00493 00494 } // end namespace clang 00495 00496 #endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H