diff options
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/AnalysisContext.cpp | 8 | ||||
-rw-r--r-- | lib/Analysis/CFG.cpp | 69 | ||||
-rw-r--r-- | lib/Analysis/CocoaConventions.cpp | 1 | ||||
-rw-r--r-- | lib/Analysis/LiveVariables.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/UninitializedValues.cpp | 51 |
5 files changed, 60 insertions, 71 deletions
diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index ddc5e887031b..678f02fd71fb 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -78,16 +78,16 @@ void AnalysisContext::registerForcedBlockExpression(const Stmt *stmt) { if (!forcedBlkExprs) forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs(); // Default construct an entry for 'stmt'. - if (const ParenExpr *pe = dyn_cast<ParenExpr>(stmt)) - stmt = pe->IgnoreParens(); + if (const Expr *e = dyn_cast<Expr>(stmt)) + stmt = e->IgnoreParens(); (void) (*forcedBlkExprs)[stmt]; } const CFGBlock * AnalysisContext::getBlockForRegisteredExpression(const Stmt *stmt) { assert(forcedBlkExprs); - if (const ParenExpr *pe = dyn_cast<ParenExpr>(stmt)) - stmt = pe->IgnoreParens(); + if (const Expr *e = dyn_cast<Expr>(stmt)) + stmt = e->IgnoreParens(); CFG::BuildOptions::ForcedBlkExprs::const_iterator itr = forcedBlkExprs->find(stmt); assert(itr != forcedBlkExprs->end()); diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index de16334ce137..3e540203eaa0 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -320,7 +320,6 @@ private: AddStmtChoice asc); CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, AddStmtChoice asc); - CFGBlock *VisitCXXMemberCallExpr(CXXMemberCallExpr *C, AddStmtChoice asc); CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc); CFGBlock *VisitCaseStmt(CaseStmt *C); CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); @@ -398,6 +397,8 @@ private: if (alwaysAdd(S)) cachedEntry->second = B; + // All block-level expressions should have already been IgnoreParens()ed. + assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S); B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext()); } void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) { @@ -444,7 +445,7 @@ private: return Result.Val.getInt().getBoolValue(); if (Result.Val.isLValue()) { - Expr *e = Result.Val.getLValueBase(); + const Expr *e = Result.Val.getLValueBase(); const CharUnits &c = Result.Val.getLValueOffset(); if (!e && c.isZero()) return false; @@ -842,11 +843,14 @@ void CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock* Blk, /// blocks for ternary operators, &&, and ||. We also process "," and /// DeclStmts (which may contain nested control-flow). CFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { -tryAgain: if (!S) { badCFG = true; return 0; } + + if (Expr *E = dyn_cast<Expr>(S)) + S = E->IgnoreParens(); + switch (S->getStmtClass()) { default: return VisitStmt(S, asc); @@ -868,6 +872,7 @@ tryAgain: case Stmt::CallExprClass: case Stmt::CXXOperatorCallExprClass: + case Stmt::CXXMemberCallExprClass: return VisitCallExpr(cast<CallExpr>(S), asc); case Stmt::CaseStmtClass: @@ -903,9 +908,6 @@ tryAgain: case Stmt::CXXTemporaryObjectExprClass: return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc); - case Stmt::CXXMemberCallExprClass: - return VisitCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), asc); - case Stmt::CXXThrowExprClass: return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); @@ -960,10 +962,6 @@ tryAgain: case Stmt::ObjCForCollectionStmtClass: return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); - case Stmt::ParenExprClass: - S = cast<ParenExpr>(S)->getSubExpr(); - goto tryAgain; - case Stmt::NullStmtClass: return Block; @@ -1153,12 +1151,19 @@ static bool CanThrow(Expr *E, ASTContext &Ctx) { } CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { - // If this is a call to a no-return function, this stops the block here. - bool NoReturn = false; - if (getFunctionExtInfo(*C->getCallee()->getType()).getNoReturn()) { - NoReturn = true; + // Compute the callee type. + QualType calleeType = C->getCallee()->getType(); + if (calleeType == Context->BoundMemberTy) { + QualType boundType = Expr::findBoundMemberType(C->getCallee()); + + // We should only get a null bound type if processing a dependent + // CFG. Recover by assuming nothing. + if (!boundType.isNull()) calleeType = boundType; } + // If this is a call to a no-return function, this stops the block here. + bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn(); + bool AddEHEdge = false; // Languages without exceptions are assumed to not throw. @@ -1314,6 +1319,12 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, } CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { + // Check if the Decl is for an __label__. If so, elide it from the + // CFG entirely. + if (isa<LabelDecl>(*DS->decl_begin())) + return Block; + + // This case also handles static_asserts. if (DS->isSingleDecl()) return VisitDeclSubExpr(DS); @@ -1346,7 +1357,14 @@ CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { /// DeclStmts and initializers in them. CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt* DS) { assert(DS->isSingleDecl() && "Can handle single declarations only."); - + Decl *D = DS->getSingleDecl(); + + if (isa<StaticAssertDecl>(D)) { + // static_asserts aren't added to the CFG because they do not impact + // runtime semantics. + return Block; + } + VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); if (!VD) { @@ -2686,13 +2704,6 @@ CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, return VisitChildren(C); } -CFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C, - AddStmtChoice asc) { - autoCreateBlock(); - appendStmt(Block, C); - return VisitChildren(C); -} - CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc) { if (asc.alwaysAdd(*this, E)) { @@ -3039,6 +3050,7 @@ static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { if (!CS) continue; if (Expr* Exp = dyn_cast<Expr>(CS->getStmt())) { + assert((Exp->IgnoreParens() == Exp) && "No parens on block-level exps"); if (BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) { // Assignment expressions that are not nested within another @@ -3046,13 +3058,16 @@ static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { // another expression. if (B->isAssignmentOp() && !SubExprAssignments.count(Exp)) continue; - } else if (const StmtExpr* Terminator = dyn_cast<StmtExpr>(Exp)) { + } else if (const StmtExpr* SE = dyn_cast<StmtExpr>(Exp)) { // Special handling for statement expressions. The last statement in // the statement expression is also a block-level expr. - const CompoundStmt* C = Terminator->getSubStmt(); + const CompoundStmt* C = SE->getSubStmt(); if (!C->body_empty()) { + const Stmt *Last = C->body_back(); + if (const Expr *LastEx = dyn_cast<Expr>(Last)) + Last = LastEx->IgnoreParens(); unsigned x = M->size(); - (*M)[C->body_back()] = x; + (*M)[Last] = x; } } @@ -3066,8 +3081,8 @@ static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { Stmt* S = (*I)->getTerminatorCondition(); if (S && M->find(S) == M->end()) { - unsigned x = M->size(); - (*M)[S] = x; + unsigned x = M->size(); + (*M)[S] = x; } } diff --git a/lib/Analysis/CocoaConventions.cpp b/lib/Analysis/CocoaConventions.cpp index 4c62f36e6c92..946c38c875d5 100644 --- a/lib/Analysis/CocoaConventions.cpp +++ b/lib/Analysis/CocoaConventions.cpp @@ -44,6 +44,7 @@ cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S) { case OMF_release: case OMF_retain: case OMF_retainCount: + case OMF_self: return NoConvention; case OMF_init: diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp index 303dc0f604d7..7b36f85ab62c 100644 --- a/lib/Analysis/LiveVariables.cpp +++ b/lib/Analysis/LiveVariables.cpp @@ -157,7 +157,7 @@ void TransferFuncs::Visit(Stmt *S) { } else { // For block-level expressions, mark that they are live. - LiveState(S,AD) = Alive; + LiveState(S, AD) = Alive; } } diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp index 88a2db751a43..e80e282813af 100644 --- a/lib/Analysis/UninitializedValues.cpp +++ b/lib/Analysis/UninitializedValues.cpp @@ -14,7 +14,7 @@ #include <utility> #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/PackedVector.h" #include "llvm/ADT/DenseMap.h" #include "clang/AST/Decl.h" #include "clang/Analysis/CFG.h" @@ -93,39 +93,8 @@ static bool isAlwaysUninit(const Value v) { } namespace { -class ValueVector { - llvm::BitVector vec; -public: - ValueVector() {} - ValueVector(unsigned size) : vec(size << 1) {} - void resize(unsigned n) { vec.resize(n << 1); } - void merge(const ValueVector &rhs) { vec |= rhs.vec; } - bool operator!=(const ValueVector &rhs) const { return vec != rhs.vec; } - void reset() { vec.reset(); } - - class reference { - ValueVector &vv; - const unsigned idx; - - reference(); // Undefined - public: - reference(ValueVector &vv, unsigned idx) : vv(vv), idx(idx) {} - ~reference() {} - - reference &operator=(Value v) { - vv.vec[idx << 1] = (((unsigned) v) & 0x1) ? true : false; - vv.vec[(idx << 1) | 1] = (((unsigned) v) & 0x2) ? true : false; - return *this; - } - operator Value() { - unsigned x = (vv.vec[idx << 1] ? 1 : 0) | (vv.vec[(idx << 1) | 1] ? 2 :0); - return (Value) x; - } - }; - - reference operator[](unsigned idx) { return reference(*this, idx); } -}; +typedef llvm::PackedVector<Value, 2> ValueVector; typedef std::pair<ValueVector *, ValueVector *> BVPair; class CFGBlockValues { @@ -214,11 +183,15 @@ static BinaryOperator *getLogicalOperatorInChain(const CFGBlock *block) { if (!b || !b->isLogicalOp()) return 0; - if (block->pred_size() == 2 && - ((block->succ_size() == 2 && block->getTerminatorCondition() == b) || - block->size() == 1)) - return b; - + if (block->pred_size() == 2) { + if (block->getTerminatorCondition() == b) { + if (block->succ_size() == 2) + return b; + } + else if (block->size() == 1) + return b; + } + return 0; } @@ -255,7 +228,7 @@ void CFGBlockValues::mergeIntoScratch(ValueVector const &source, if (isFirst) scratch = source; else - scratch.merge(source); + scratch |= source; } #if 0 static void printVector(const CFGBlock *block, ValueVector &bv, |