From: Zhanyong Wan Date: Wed, 24 Nov 2010 03:28:53 +0000 (+0000) Subject: Refactor AddStmtChoice to make it easier to use; also add comments on how the class... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=94a3dcf146451eb6b0192873e267c4cb0f6147e8;p=clang Refactor AddStmtChoice to make it easier to use; also add comments on how the class works. Reviewed by kremenek. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120080 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 4b89a54023..b371f6a519 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -36,20 +36,52 @@ static SourceLocation GetEndLoc(Decl* D) { return D->getLocation(); } +/// The CFG builder uses a recursive algorithm to build the CFG. When +/// we process an expression, sometimes we know that we must add the +/// subexpressions as block-level expressions. For example: +/// +/// exp1 || exp2 +/// +/// When processing the '||' expression, we know that exp1 and exp2 +/// need to be added as block-level expressions, even though they +/// might not normally need to be. AddStmtChoice records this +/// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then +/// the builder has an option not to add a subexpression as a +/// block-level expression. +/// +/// The lvalue bit captures whether or not a subexpression needs to +/// be processed as an lvalue. That information needs to be recorded +/// in the CFG for block-level expressions so that analyses do the +/// right thing when traversing the CFG (since such subexpressions +/// will be seen before their parent expression is processed). class AddStmtChoice { public: enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1, AsLValueNotAlwaysAdd = 2, - AlwaysAddAsLValue = 3 }; + AsLValueAlwaysAdd = 3 }; - AddStmtChoice(Kind kind) : k(kind) {} + AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {} - bool alwaysAdd() const { return (unsigned)k & 0x1; } - bool asLValue() const { return k >= AsLValueNotAlwaysAdd; } + bool alwaysAdd() const { return kind & AlwaysAdd; } + bool asLValue() const { return kind >= AsLValueNotAlwaysAdd; } + + /// Return a copy of this object, except with the 'always-add' bit + /// set as specified. + AddStmtChoice withAlwaysAdd(bool alwaysAdd) const { + return AddStmtChoice(alwaysAdd ? Kind(kind | AlwaysAdd) : + Kind(kind & ~AlwaysAdd)); + } + + /// Return a copy of this object, except with the 'as-lvalue' bit + /// set as specified. + AddStmtChoice withAsLValue(bool asLVal) const { + return AddStmtChoice(asLVal ? Kind(kind | AsLValueNotAlwaysAdd) : + Kind(kind & ~AsLValueNotAlwaysAdd)); + } private: - Kind k; + Kind kind; }; /// LocalScope - Node in tree of local scopes created for C++ implicit @@ -536,9 +568,7 @@ CFGBlock *CFGBuilder::addInitializer(CXXBaseOrMemberInitializer *I) { appendInitializer(Block, I); if (Init) { - AddStmtChoice asc = IsReference - ? AddStmtChoice::AsLValueNotAlwaysAdd - : AddStmtChoice::NotAlwaysAdd; + AddStmtChoice asc = AddStmtChoice().withAsLValue(IsReference); if (HasTemporaries) // For expression with temporaries go directly to subexpression to omit // generating destructors for the second time. @@ -934,9 +964,7 @@ CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, } bool asLVal = U->isIncrementDecrementOp(); - return Visit(U->getSubExpr(), - asLVal ? AddStmtChoice::AsLValueNotAlwaysAdd : - AddStmtChoice::NotAlwaysAdd); + return Visit(U->getSubExpr(), AddStmtChoice().withAsLValue(asLVal)); } CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, @@ -1087,12 +1115,8 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { if (!CanThrow(C->getCallee())) AddEHEdge = false; - if (!NoReturn && !AddEHEdge) { - if (asc.asLValue()) - return VisitStmt(C, AddStmtChoice::AlwaysAddAsLValue); - else - return VisitStmt(C, AddStmtChoice::AlwaysAdd); - } + if (!NoReturn && !AddEHEdge) + return VisitStmt(C, asc.withAlwaysAdd(true)); if (Block) { Succ = Block; @@ -1125,18 +1149,16 @@ CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, if (badCFG) return 0; - asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue - : AddStmtChoice::AlwaysAdd; - + AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); Succ = ConfluenceBlock; Block = NULL; - CFGBlock* LHSBlock = Visit(C->getLHS(), asc); + CFGBlock* LHSBlock = Visit(C->getLHS(), alwaysAdd); if (badCFG) return 0; Succ = ConfluenceBlock; Block = NULL; - CFGBlock* RHSBlock = Visit(C->getRHS(), asc); + CFGBlock* RHSBlock = Visit(C->getRHS(), alwaysAdd); if (badCFG) return 0; @@ -1177,8 +1199,7 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, if (badCFG) return 0; - asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue - : AddStmtChoice::AlwaysAdd; + AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); // Create a block for the LHS expression if there is an LHS expression. A // GCC extension allows LHS to be NULL, causing the condition to be the @@ -1188,7 +1209,7 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, Block = NULL; CFGBlock* LHSBlock = NULL; if (C->getLHS()) { - LHSBlock = Visit(C->getLHS(), asc); + LHSBlock = Visit(C->getLHS(), alwaysAdd); if (badCFG) return 0; Block = NULL; @@ -1196,7 +1217,7 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, // Create the block for the RHS expression. Succ = ConfluenceBlock; - CFGBlock* RHSBlock = Visit(C->getRHS(), asc); + CFGBlock* RHSBlock = Visit(C->getRHS(), alwaysAdd); if (badCFG) return 0; @@ -1297,9 +1318,7 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt* DS) { AppendStmt(Block, DS); if (Init) { - AddStmtChoice asc = IsReference - ? AddStmtChoice::AsLValueNotAlwaysAdd - : AddStmtChoice::NotAlwaysAdd; + AddStmtChoice asc = AddStmtChoice().withAsLValue(IsReference); if (HasTemporaries) // For expression with temporaries go directly to subexpression to omit // generating destructors for the second time. @@ -1661,8 +1680,7 @@ CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { AppendStmt(Block, M, asc); } return Visit(M->getBase(), - M->isArrow() ? AddStmtChoice::NotAlwaysAdd - : AddStmtChoice::AsLValueNotAlwaysAdd); + AddStmtChoice().withAsLValue(!M->isArrow())); } CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { @@ -2385,9 +2403,7 @@ CFGBlock *CFGBuilder::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E, // Full expression has to be added as CFGStmt so it will be sequenced // before destructors of it's temporaries. - asc = asc.asLValue() - ? AddStmtChoice::AlwaysAddAsLValue - : AddStmtChoice::AlwaysAdd; + asc = asc.withAlwaysAdd(true); } return Visit(E->getSubExpr(), asc); } @@ -2399,19 +2415,17 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, AppendStmt(Block, E, asc); // We do not want to propagate the AlwaysAdd property. - asc = AddStmtChoice(asc.asLValue() ? AddStmtChoice::AsLValueNotAlwaysAdd - : AddStmtChoice::NotAlwaysAdd); + asc = asc.withAlwaysAdd(false); } return Visit(E->getSubExpr(), asc); } CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc) { - AddStmtChoice::Kind K = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue - : AddStmtChoice::AlwaysAdd; autoCreateBlock(); if (!C->isElidable()) - AppendStmt(Block, C, AddStmtChoice(K)); + AppendStmt(Block, C, asc.withAlwaysAdd(true)); + return VisitChildren(C); } @@ -2421,27 +2435,22 @@ CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, autoCreateBlock(); AppendStmt(Block, E, asc); // We do not want to propagate the AlwaysAdd property. - asc = AddStmtChoice(asc.asLValue() ? AddStmtChoice::AsLValueNotAlwaysAdd - : AddStmtChoice::NotAlwaysAdd); + asc = asc.withAlwaysAdd(false); } return Visit(E->getSubExpr(), asc); } CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, AddStmtChoice asc) { - AddStmtChoice::Kind K = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue - : AddStmtChoice::AlwaysAdd; autoCreateBlock(); - AppendStmt(Block, C, AddStmtChoice(K)); + AppendStmt(Block, C, asc.withAlwaysAdd(true)); return VisitChildren(C); } CFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C, AddStmtChoice asc) { - AddStmtChoice::Kind K = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue - : AddStmtChoice::AlwaysAdd; autoCreateBlock(); - AppendStmt(Block, C, AddStmtChoice(K)); + AppendStmt(Block, C, asc.withAlwaysAdd(true)); return VisitChildren(C); } @@ -2451,8 +2460,7 @@ CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, autoCreateBlock(); AppendStmt(Block, E, asc); // We do not want to propagate the AlwaysAdd property. - asc = AddStmtChoice(asc.asLValue() ? AddStmtChoice::AsLValueNotAlwaysAdd - : AddStmtChoice::NotAlwaysAdd); + asc = asc.withAlwaysAdd(false); } return Visit(E->getSubExpr(), asc); }