summaryrefslogtreecommitdiffstats
path: root/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Analysis/Analyses/ThreadSafetyCommon.h')
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyCommon.h505
1 files changed, 0 insertions, 505 deletions
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
deleted file mode 100644
index e357013..0000000
--- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ /dev/null
@@ -1,505 +0,0 @@
-//===- ThreadSafetyCommon.h ------------------------------------*- C++ --*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Parts of thread safety analysis that are not specific to thread safety
-// itself have been factored into classes here, where they can be potentially
-// used by other analyses. Currently these include:
-//
-// * Generalize clang CFG visitors.
-// * Conversion of the clang CFG to SSA form.
-// * Translation of clang Exprs to TIL SExprs
-//
-// UNDER CONSTRUCTION. USE AT YOUR OWN RISK.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
-#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
-
-#include "clang/Analysis/Analyses/PostOrderCFGView.h"
-#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
-#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
-#include "clang/Analysis/AnalysisContext.h"
-#include "clang/Basic/OperatorKinds.h"
-#include <memory>
-#include <ostream>
-#include <sstream>
-#include <vector>
-
-
-namespace clang {
-namespace threadSafety {
-
-
-// Various helper functions on til::SExpr
-namespace sx {
-
-inline bool equals(const til::SExpr *E1, const til::SExpr *E2) {
- return til::EqualsComparator::compareExprs(E1, E2);
-}
-
-inline bool matches(const til::SExpr *E1, const til::SExpr *E2) {
- // We treat a top-level wildcard as the "univsersal" lock.
- // It matches everything for the purpose of checking locks, but not
- // for unlocking them.
- if (isa<til::Wildcard>(E1))
- return isa<til::Wildcard>(E2);
- if (isa<til::Wildcard>(E2))
- return isa<til::Wildcard>(E1);
-
- return til::MatchComparator::compareExprs(E1, E2);
-}
-
-inline bool partiallyMatches(const til::SExpr *E1, const til::SExpr *E2) {
- const auto *PE1 = dyn_cast_or_null<til::Project>(E1);
- if (!PE1)
- return false;
- const auto *PE2 = dyn_cast_or_null<til::Project>(E2);
- if (!PE2)
- return false;
- return PE1->clangDecl() == PE2->clangDecl();
-}
-
-inline std::string toString(const til::SExpr *E) {
- std::stringstream ss;
- til::StdPrinter::print(E, ss);
- return ss.str();
-}
-
-} // end namespace sx
-
-
-
-// This class defines the interface of a clang CFG Visitor.
-// CFGWalker will invoke the following methods.
-// Note that methods are not virtual; the visitor is templatized.
-class CFGVisitor {
- // Enter the CFG for Decl D, and perform any initial setup operations.
- void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First) {}
-
- // Enter a CFGBlock.
- void enterCFGBlock(const CFGBlock *B) {}
-
- // Returns true if this visitor implements handlePredecessor
- bool visitPredecessors() { return true; }
-
- // Process a predecessor edge.
- void handlePredecessor(const CFGBlock *Pred) {}
-
- // Process a successor back edge to a previously visited block.
- void handlePredecessorBackEdge(const CFGBlock *Pred) {}
-
- // Called just before processing statements.
- void enterCFGBlockBody(const CFGBlock *B) {}
-
- // Process an ordinary statement.
- void handleStatement(const Stmt *S) {}
-
- // Process a destructor call
- void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD) {}
-
- // Called after all statements have been handled.
- void exitCFGBlockBody(const CFGBlock *B) {}
-
- // Return true
- bool visitSuccessors() { return true; }
-
- // Process a successor edge.
- void handleSuccessor(const CFGBlock *Succ) {}
-
- // Process a successor back edge to a previously visited block.
- void handleSuccessorBackEdge(const CFGBlock *Succ) {}
-
- // Leave a CFGBlock.
- void exitCFGBlock(const CFGBlock *B) {}
-
- // Leave the CFG, and perform any final cleanup operations.
- void exitCFG(const CFGBlock *Last) {}
-};
-
-
-// Walks the clang CFG, and invokes methods on a given CFGVisitor.
-class CFGWalker {
-public:
- CFGWalker() : CFGraph(nullptr), ACtx(nullptr), SortedGraph(nullptr) {}
-
- // Initialize the CFGWalker. This setup only needs to be done once, even
- // if there are multiple passes over the CFG.
- bool init(AnalysisDeclContext &AC) {
- ACtx = &AC;
- CFGraph = AC.getCFG();
- if (!CFGraph)
- return false;
-
- // Ignore anonymous functions.
- if (!dyn_cast_or_null<NamedDecl>(AC.getDecl()))
- return false;
-
- SortedGraph = AC.getAnalysis<PostOrderCFGView>();
- if (!SortedGraph)
- return false;
-
- return true;
- }
-
- // Traverse the CFG, calling methods on V as appropriate.
- template <class Visitor>
- void walk(Visitor &V) {
- PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
-
- V.enterCFG(CFGraph, getDecl(), &CFGraph->getEntry());
-
- for (const auto *CurrBlock : *SortedGraph) {
- VisitedBlocks.insert(CurrBlock);
-
- V.enterCFGBlock(CurrBlock);
-
- // Process predecessors, handling back edges last
- if (V.visitPredecessors()) {
- SmallVector<CFGBlock*, 4> BackEdges;
- // Process successors
- for (CFGBlock::const_pred_iterator SI = CurrBlock->pred_begin(),
- SE = CurrBlock->pred_end();
- SI != SE; ++SI) {
- if (*SI == nullptr)
- continue;
-
- if (!VisitedBlocks.alreadySet(*SI)) {
- BackEdges.push_back(*SI);
- continue;
- }
- V.handlePredecessor(*SI);
- }
-
- for (auto *Blk : BackEdges)
- V.handlePredecessorBackEdge(Blk);
- }
-
- V.enterCFGBlockBody(CurrBlock);
-
- // Process statements
- for (const auto &BI : *CurrBlock) {
- switch (BI.getKind()) {
- case CFGElement::Statement: {
- V.handleStatement(BI.castAs<CFGStmt>().getStmt());
- break;
- }
- case CFGElement::AutomaticObjectDtor: {
- CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>();
- CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>(
- AD.getDestructorDecl(ACtx->getASTContext()));
- VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl());
- V.handleDestructorCall(VD, DD);
- break;
- }
- default:
- break;
- }
- }
-
- V.exitCFGBlockBody(CurrBlock);
-
- // Process successors, handling back edges first.
- if (V.visitSuccessors()) {
- SmallVector<CFGBlock*, 8> ForwardEdges;
-
- // Process successors
- for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
- SE = CurrBlock->succ_end();
- SI != SE; ++SI) {
- if (*SI == nullptr)
- continue;
-
- if (!VisitedBlocks.alreadySet(*SI)) {
- ForwardEdges.push_back(*SI);
- continue;
- }
- V.handleSuccessorBackEdge(*SI);
- }
-
- for (auto *Blk : ForwardEdges)
- V.handleSuccessor(Blk);
- }
-
- V.exitCFGBlock(CurrBlock);
- }
- V.exitCFG(&CFGraph->getExit());
- }
-
- const CFG *getGraph() const { return CFGraph; }
- CFG *getGraph() { return CFGraph; }
-
- const NamedDecl *getDecl() const {
- return dyn_cast<NamedDecl>(ACtx->getDecl());
- }
-
- const PostOrderCFGView *getSortedGraph() const { return SortedGraph; }
-
-private:
- CFG *CFGraph;
- AnalysisDeclContext *ACtx;
- PostOrderCFGView *SortedGraph;
-};
-
-
-
-
-class CapabilityExpr {
- // TODO: move this back into ThreadSafety.cpp
- // This is specific to thread safety. It is here because
- // translateAttrExpr needs it, but that should be moved too.
-
-private:
- const til::SExpr* CapExpr; ///< The capability expression.
- bool Negated; ///< True if this is a negative capability
-
-public:
- CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {}
-
- const til::SExpr* sexpr() const { return CapExpr; }
- bool negative() const { return Negated; }
-
- CapabilityExpr operator!() const {
- return CapabilityExpr(CapExpr, !Negated);
- }
-
- bool equals(const CapabilityExpr &other) const {
- return (Negated == other.Negated) && sx::equals(CapExpr, other.CapExpr);
- }
-
- bool matches(const CapabilityExpr &other) const {
- return (Negated == other.Negated) && sx::matches(CapExpr, other.CapExpr);
- }
-
- bool matchesUniv(const CapabilityExpr &CapE) const {
- return isUniversal() || matches(CapE);
- }
-
- bool partiallyMatches(const CapabilityExpr &other) const {
- return (Negated == other.Negated) &&
- sx::partiallyMatches(CapExpr, other.CapExpr);
- }
-
- const ValueDecl* valueDecl() const {
- if (Negated || CapExpr == nullptr)
- return nullptr;
- if (auto *P = dyn_cast<til::Project>(CapExpr))
- return P->clangDecl();
- if (auto *P = dyn_cast<til::LiteralPtr>(CapExpr))
- return P->clangDecl();
- return nullptr;
- }
-
- std::string toString() const {
- if (Negated)
- return "!" + sx::toString(CapExpr);
- return sx::toString(CapExpr);
- }
-
- bool shouldIgnore() const { return CapExpr == nullptr; }
-
- bool isInvalid() const { return sexpr() && isa<til::Undefined>(sexpr()); }
-
- bool isUniversal() const { return sexpr() && isa<til::Wildcard>(sexpr()); }
-};
-
-
-
-// Translate clang::Expr to til::SExpr.
-class SExprBuilder {
-public:
- /// \brief Encapsulates the lexical context of a function call. The lexical
- /// context includes the arguments to the call, including the implicit object
- /// argument. When an attribute containing a mutex expression is attached to
- /// a method, the expression may refer to formal parameters of the method.
- /// Actual arguments must be substituted for formal parameters to derive
- /// the appropriate mutex expression in the lexical context where the function
- /// is called. PrevCtx holds the context in which the arguments themselves
- /// should be evaluated; multiple calling contexts can be chained together
- /// by the lock_returned attribute.
- struct CallingContext {
- CallingContext *Prev; // The previous context; or 0 if none.
- const NamedDecl *AttrDecl; // The decl to which the attr is attached.
- const Expr *SelfArg; // Implicit object argument -- e.g. 'this'
- unsigned NumArgs; // Number of funArgs
- const Expr *const *FunArgs; // Function arguments
- bool SelfArrow; // is Self referred to with -> or .?
-
- CallingContext(CallingContext *P, const NamedDecl *D = nullptr)
- : Prev(P), AttrDecl(D), SelfArg(nullptr),
- NumArgs(0), FunArgs(nullptr), SelfArrow(false)
- {}
- };
-
- SExprBuilder(til::MemRegionRef A)
- : Arena(A), SelfVar(nullptr), Scfg(nullptr), CurrentBB(nullptr),
- CurrentBlockInfo(nullptr) {
- // FIXME: we don't always have a self-variable.
- SelfVar = new (Arena) til::Variable(nullptr);
- SelfVar->setKind(til::Variable::VK_SFun);
- }
-
- // Translate a clang expression in an attribute to a til::SExpr.
- // Constructs the context from D, DeclExp, and SelfDecl.
- CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D,
- const Expr *DeclExp, VarDecl *SelfD=nullptr);
-
- CapabilityExpr translateAttrExpr(const Expr *AttrExp, CallingContext *Ctx);
-
- // Translate a clang statement or expression to a TIL expression.
- // Also performs substitution of variables; Ctx provides the context.
- // Dispatches on the type of S.
- til::SExpr *translate(const Stmt *S, CallingContext *Ctx);
- til::SCFG *buildCFG(CFGWalker &Walker);
-
- til::SExpr *lookupStmt(const Stmt *S);
-
- til::BasicBlock *lookupBlock(const CFGBlock *B) {
- return BlockMap[B->getBlockID()];
- }
-
- const til::SCFG *getCFG() const { return Scfg; }
- til::SCFG *getCFG() { return Scfg; }
-
-private:
- til::SExpr *translateDeclRefExpr(const DeclRefExpr *DRE,
- CallingContext *Ctx) ;
- til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx);
- til::SExpr *translateMemberExpr(const MemberExpr *ME, CallingContext *Ctx);
- til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx,
- const Expr *SelfE = nullptr);
- til::SExpr *translateCXXMemberCallExpr(const CXXMemberCallExpr *ME,
- CallingContext *Ctx);
- til::SExpr *translateCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE,
- CallingContext *Ctx);
- til::SExpr *translateUnaryOperator(const UnaryOperator *UO,
- CallingContext *Ctx);
- til::SExpr *translateBinOp(til::TIL_BinaryOpcode Op,
- const BinaryOperator *BO,
- CallingContext *Ctx, bool Reverse = false);
- til::SExpr *translateBinAssign(til::TIL_BinaryOpcode Op,
- const BinaryOperator *BO,
- CallingContext *Ctx, bool Assign = false);
- til::SExpr *translateBinaryOperator(const BinaryOperator *BO,
- CallingContext *Ctx);
- til::SExpr *translateCastExpr(const CastExpr *CE, CallingContext *Ctx);
- til::SExpr *translateArraySubscriptExpr(const ArraySubscriptExpr *E,
- CallingContext *Ctx);
- til::SExpr *translateAbstractConditionalOperator(
- const AbstractConditionalOperator *C, CallingContext *Ctx);
-
- til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx);
-
- // Map from statements in the clang CFG to SExprs in the til::SCFG.
- typedef llvm::DenseMap<const Stmt*, til::SExpr*> StatementMap;
-
- // Map from clang local variables to indices in a LVarDefinitionMap.
- typedef llvm::DenseMap<const ValueDecl *, unsigned> LVarIndexMap;
-
- // Map from local variable indices to SSA variables (or constants).
- typedef std::pair<const ValueDecl *, til::SExpr *> NameVarPair;
- typedef CopyOnWriteVector<NameVarPair> LVarDefinitionMap;
-
- struct BlockInfo {
- LVarDefinitionMap ExitMap;
- bool HasBackEdges;
- unsigned UnprocessedSuccessors; // Successors yet to be processed
- unsigned ProcessedPredecessors; // Predecessors already processed
-
- BlockInfo()
- : HasBackEdges(false), UnprocessedSuccessors(0),
- ProcessedPredecessors(0) {}
- BlockInfo(BlockInfo &&RHS)
- : ExitMap(std::move(RHS.ExitMap)),
- HasBackEdges(RHS.HasBackEdges),
- UnprocessedSuccessors(RHS.UnprocessedSuccessors),
- ProcessedPredecessors(RHS.ProcessedPredecessors) {}
-
- BlockInfo &operator=(BlockInfo &&RHS) {
- if (this != &RHS) {
- ExitMap = std::move(RHS.ExitMap);
- HasBackEdges = RHS.HasBackEdges;
- UnprocessedSuccessors = RHS.UnprocessedSuccessors;
- ProcessedPredecessors = RHS.ProcessedPredecessors;
- }
- return *this;
- }
-
- private:
- BlockInfo(const BlockInfo &) = delete;
- void operator=(const BlockInfo &) = delete;
- };
-
- // We implement the CFGVisitor API
- friend class CFGWalker;
-
- void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First);
- void enterCFGBlock(const CFGBlock *B);
- bool visitPredecessors() { return true; }
- void handlePredecessor(const CFGBlock *Pred);
- void handlePredecessorBackEdge(const CFGBlock *Pred);
- void enterCFGBlockBody(const CFGBlock *B);
- void handleStatement(const Stmt *S);
- void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD);
- void exitCFGBlockBody(const CFGBlock *B);
- bool visitSuccessors() { return true; }
- void handleSuccessor(const CFGBlock *Succ);
- void handleSuccessorBackEdge(const CFGBlock *Succ);
- void exitCFGBlock(const CFGBlock *B);
- void exitCFG(const CFGBlock *Last);
-
- void insertStmt(const Stmt *S, til::SExpr *E) {
- SMap.insert(std::make_pair(S, E));
- }
- til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD);
-
- til::SExpr *addStatement(til::SExpr *E, const Stmt *S,
- const ValueDecl *VD = nullptr);
- til::SExpr *lookupVarDecl(const ValueDecl *VD);
- til::SExpr *addVarDecl(const ValueDecl *VD, til::SExpr *E);
- til::SExpr *updateVarDecl(const ValueDecl *VD, til::SExpr *E);
-
- void makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E);
- void mergeEntryMap(LVarDefinitionMap Map);
- void mergeEntryMapBackEdge();
- void mergePhiNodesBackEdge(const CFGBlock *Blk);
-
-private:
- // Set to true when parsing capability expressions, which get translated
- // inaccurately in order to hack around smart pointers etc.
- static const bool CapabilityExprMode = true;
-
- til::MemRegionRef Arena;
- til::Variable *SelfVar; // Variable to use for 'this'. May be null.
-
- til::SCFG *Scfg;
- StatementMap SMap; // Map from Stmt to TIL Variables
- LVarIndexMap LVarIdxMap; // Indices of clang local vars.
- std::vector<til::BasicBlock *> BlockMap; // Map from clang to til BBs.
- std::vector<BlockInfo> BBInfo; // Extra information per BB.
- // Indexed by clang BlockID.
-
- LVarDefinitionMap CurrentLVarMap;
- std::vector<til::Phi*> CurrentArguments;
- std::vector<til::SExpr*> CurrentInstructions;
- std::vector<til::Phi*> IncompleteArgs;
- til::BasicBlock *CurrentBB;
- BlockInfo *CurrentBlockInfo;
-};
-
-
-// Dump an SCFG to llvm::errs().
-void printSCFG(CFGWalker &Walker);
-
-
-} // end namespace threadSafety
-
-} // end namespace clang
-
-#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H
OpenPOWER on IntegriCloud