r174447 - Change subexpressions to be visited in the CFG from left-to-right.
Jordan Rose
jordan_rose at apple.com
Tue Feb 5 15:18:17 PST 2013
On Feb 5, 2013, at 14:00 , Ted Kremenek <kremenek at apple.com> wrote:
> Author: kremenek
> Date: Tue Feb 5 16:00:19 2013
> New Revision: 174447
>
> URL: http://llvm.org/viewvc/llvm-project?rev=174447&view=rev
> Log:
> Change subexpressions to be visited in the CFG from left-to-right.
>
> This is a more natural order of evaluation, and it is very important
> for visualization in the static analyzer. Within Xcode, the arrows
> will not jump from right to left, which looks very visually jarring.
> It also provides a more natural location for dataflow-based diagnostics.
>
> Along the way, we found a case in the analyzer diagnostics where we
> needed to indicate that a variable was "captured" by a block.
>
> -fsyntax-only timings on sqlite3.c show no visible performance change,
> although this is just one test case.
>
> Fixes <rdar://problem/13016513>
>
> Modified:
> cfe/trunk/include/clang/AST/Expr.h
> cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
> cfe/trunk/lib/Analysis/CFG.cpp
> cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
> cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
> cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp
> cfe/trunk/test/Analysis/unix-fns.c
> cfe/trunk/test/Sema/warn-unreachable.c
>
> Modified: cfe/trunk/include/clang/AST/Expr.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=174447&r1=174446&r2=174447&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Expr.h (original)
> +++ cfe/trunk/include/clang/AST/Expr.h Tue Feb 5 16:00:19 2013
> @@ -2207,6 +2207,15 @@ public:
> return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
> }
>
> + /// This method provides fast access to all the subexpressions of
> + /// a CallExpr without going through the slower virtual child_iterator
> + /// interface. This provides efficient reverse iteration of the
> + /// subexpressions. This is currently used for CFG construction.
> + ArrayRef<Stmt*> getRawSubExprs() {
> + return ArrayRef<Stmt*>(SubExprs,
> + getNumPreArgs() + PREARGS_START + getNumArgs());
> + }
> +
> /// getNumCommas - Return the number of commas that must have been present in
> /// this function call.
> unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
>
> Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h?rev=174447&r1=174446&r2=174447&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h (original)
> +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h Tue Feb 5 16:00:19 2013
> @@ -662,6 +662,10 @@ public:
> return *this;
> }
> };
> +
> + /// Return the original region for a captured region, if
> + /// one exists.
> + const VarRegion *getOriginalRegion(const VarRegion *VR) const;
>
> referenced_vars_iterator referenced_vars_begin() const;
> referenced_vars_iterator referenced_vars_end() const;
>
> Modified: cfe/trunk/lib/Analysis/CFG.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=174447&r1=174446&r2=174447&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Analysis/CFG.cpp (original)
> +++ cfe/trunk/lib/Analysis/CFG.cpp Tue Feb 5 16:00:19 2013
> @@ -233,6 +233,43 @@ public:
> }
> };
>
> +class reverse_children {
> + llvm::SmallVector<Stmt *, 12> childrenBuf;
> + ArrayRef<Stmt*> children;
> +public:
> + reverse_children(Stmt *S);
> +
> + typedef ArrayRef<Stmt*>::reverse_iterator iterator;
> + iterator begin() const { return children.rbegin(); }
> + iterator end() const { return children.rend(); }
> +};
> +
> +
> +reverse_children::reverse_children(Stmt *S) {
> + if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
> + children = CE->getRawSubExprs();
> + return;
> + }
> + switch (S->getStmtClass()) {
> + case Stmt::InitListExprClass: {
> + InitListExpr *IE = cast<InitListExpr>(S);
> + children = llvm::makeArrayRef(reinterpret_cast<Stmt**>(IE->getInits()),
> + IE->getNumInits());
> + return;
> + }
> + default:
> + break;
> + }
> +
> + // Default case for all other statements.
> + for (Stmt::child_range I = S->children(); I; ++I) {
> + childrenBuf.push_back(*I);
> + }
> +
> + // This needs to be done *after* childrenBuf has been populated.
> + children = childrenBuf;
> +}
> +
> /// CFGBuilder - This class implements CFG construction from an AST.
> /// The builder is stateful: an instance of the builder should be used to only
> /// construct a single CFG.
> @@ -1166,14 +1203,19 @@ CFGBlock *CFGBuilder::VisitStmt(Stmt *S,
> }
>
> /// VisitChildren - Visit the children of a Stmt.
> -CFGBlock *CFGBuilder::VisitChildren(Stmt *Terminator) {
> - CFGBlock *lastBlock = Block;
> - for (Stmt::child_range I = Terminator->children(); I; ++I)
> - if (Stmt *child = *I)
> - if (CFGBlock *b = Visit(child))
> - lastBlock = b;
> +CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
> + CFGBlock *B = Block;
>
> - return lastBlock;
> + // Visit the children in their reverse order so that they appear in
> + // left-to-right (natural) order in the CFG.
> + reverse_children RChildren(S);
> + for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
> + I != E; ++I) {
> + if (Stmt *Child = *I)
> + if (CFGBlock *R = Visit(Child))
> + B = R;
> + }
> + return B;
> }
>
> CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
> @@ -3093,19 +3135,14 @@ tryAgain:
>
> CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) {
> // When visiting children for destructors we want to visit them in reverse
> - // order. Because there's no reverse iterator for children must to reverse
> - // them in helper vector.
> - typedef SmallVector<Stmt *, 4> ChildrenVect;
> - ChildrenVect ChildrenRev;
> - for (Stmt::child_range I = E->children(); I; ++I) {
> - if (*I) ChildrenRev.push_back(*I);
> - }
> -
> + // order that they will appear in the CFG. Because the CFG is built
> + // bottom-up, this means we visit them in their natural order, which
> + // reverses them in the CFG.
> CFGBlock *B = Block;
> - for (ChildrenVect::reverse_iterator I = ChildrenRev.rbegin(),
> - L = ChildrenRev.rend(); I != L; ++I) {
> - if (CFGBlock *R = VisitForTemporaryDtors(*I))
> - B = R;
> + for (Stmt::child_range I = E->children(); I; ++I) {
> + if (Stmt *Child = *I)
> + if (CFGBlock *R = VisitForTemporaryDtors(Child))
> + B = R;
> }
> return B;
> }
This is wrong. Destructors must be visited in reverse order of initializers, as required by the standard.
Jordan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130205/4de4332f/attachment.html>
More information about the cfe-commits
mailing list