/// \brief The basis case walks all of the children of the statement or
/// expression, assuming they are all potentially evaluated.
void VisitStmt(Stmt *S) {
- for(Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end();
- C != CEnd; ++C)
+ for (Stmt::child_range C = S->children(); C; ++C)
this->Visit(*C);
}
};
// ----------------- Stmt traversal -----------------
//
// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating
-// over the children defined in child_begin/child_end (every stmt
-// defines these, though sometimes the range is empty). Each
-// individual Traverse* method only needs to worry about children
-// other than those. To see what child_begin()/end() does for a given
-// class, see, e.g.,
-// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
+// over the children defined in children() (every stmt defines these,
+// though sometimes the range is empty). Each individual Traverse*
+// method only needs to worry about children other than those. To see
+// what children() does for a given class, see, e.g.,
+// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
// This macro makes available a variable S, the passed-in stmt.
#define DEF_TRAVERSE_STMT(STMT, CODE) \
bool RecursiveASTVisitor<Derived>::Traverse##STMT (STMT *S) { \
TRY_TO(WalkUpFrom##STMT(S)); \
{ CODE; } \
- for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end(); \
- C != CEnd; ++C) { \
- TRY_TO(TraverseStmt(*C)); \
+ for (Stmt::child_range range = S->children(); range; ++range) { \
+ TRY_TO(TraverseStmt(*range)); \
} \
return true; \
}
for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
TRY_TO(TraverseStmt(S->getClobber(I)));
}
- // child_begin()/end() iterates over inputExpr and outputExpr.
+ // children() iterates over inputExpr and outputExpr.
})
DEF_TRAVERSE_STMT(CXXCatchStmt, {
TRY_TO(TraverseDecl(S->getExceptionDecl()));
- // child_begin()/end() iterates over the handler block.
+ // children() iterates over the handler block.
})
DEF_TRAVERSE_STMT(DeclStmt, {
I != E; ++I) {
TRY_TO(TraverseDecl(*I));
}
- // Suppress the default iteration over child_begin/end by
+ // Suppress the default iteration over children() by
// returning. Here's why: A DeclStmt looks like 'type var [=
// initializer]'. The decls above already traverse over the
// initializers, so we don't have to do it again (which
- // child_begin/end would do).
+ // children() would do).
return true;
})
S = Syn;
TRY_TO(WalkUpFromInitListExpr(S));
// All we need are the default actions. FIXME: use a helper function.
- for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end();
- C != CEnd; ++C) {
- TRY_TO(TraverseStmt(*C));
+ for (Stmt::child_range range = S->children(); range; ++range) {
+ TRY_TO(TraverseStmt(*range));
}
return true;
}
StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
};
-typedef std::pair<StmtIterator,StmtIterator> StmtRange;
-typedef std::pair<ConstStmtIterator,ConstStmtIterator> ConstStmtRange;
+/// A range of statement iterators.
+///
+/// This class provides some extra functionality beyond std::pair
+/// in order to allow the following idiom:
+/// for (StmtRange range = stmt->children(); range; ++range)
+struct StmtRange : std::pair<StmtIterator,StmtIterator> {
+ StmtRange() {}
+ StmtRange(const StmtIterator &begin, const StmtIterator &end)
+ : std::pair<StmtIterator,StmtIterator>(begin, end) {}
+
+ bool empty() const { return first == second; }
+ operator bool() const { return !empty(); }
+
+ Stmt *operator->() const { return first.operator->(); }
+ Stmt *&operator*() const { return first.operator*(); }
+
+ StmtRange &operator++() {
+ assert(!empty() && "incrementing on empty range");
+ ++first;
+ return *this;
+ }
-inline StmtIterator begin(StmtRange range) { return range.first; }
-inline StmtIterator end(StmtRange range) { return range.second; }
+ StmtRange operator++(int) {
+ assert(!empty() && "incrementing on empty range");
+ StmtRange copy = *this;
+ ++first;
+ return copy;
+ }
-inline ConstStmtIterator begin(ConstStmtRange range) { return range.first; }
-inline ConstStmtIterator end(ConstStmtRange range) { return range.second; }
+ friend const StmtIterator &begin(const StmtRange &range) {
+ return range.first;
+ }
+ friend const StmtIterator &end(const StmtRange &range) {
+ return range.second;
+ }
+};
+
+/// A range of const statement iterators.
+///
+/// This class provides some extra functionality beyond std::pair
+/// in order to allow the following idiom:
+/// for (ConstStmtRange range = stmt->children(); range; ++range)
+struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
+ ConstStmtRange() {}
+ ConstStmtRange(const ConstStmtIterator &begin,
+ const ConstStmtIterator &end)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
+ ConstStmtRange(const StmtRange &range)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second)
+ {}
+ ConstStmtRange(const StmtIterator &begin, const StmtIterator &end)
+ : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
+
+ bool empty() const { return first == second; }
+ operator bool() const { return !empty(); }
+
+ const Stmt *operator->() const { return first.operator->(); }
+ const Stmt *operator*() const { return first.operator*(); }
+
+ ConstStmtRange &operator++() {
+ assert(!empty() && "incrementing on empty range");
+ ++first;
+ return *this;
+ }
+
+ ConstStmtRange operator++(int) {
+ assert(!empty() && "incrementing on empty range");
+ ConstStmtRange copy = *this;
+ ++first;
+ return copy;
+ }
+
+ friend const ConstStmtIterator &begin(const ConstStmtRange &range) {
+ return range.first;
+ }
+ friend const ConstStmtIterator &end(const ConstStmtRange &range) {
+ return range.second;
+ }
+};
} // end namespace clang
}
}
- for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)
+ for (Stmt::child_range I = S->children(); I; ++I)
if (*I) static_cast<ImplClass*>(this)->Visit(*I);
}
};
if (isa<T>(S))
return true;
- for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
- ++I)
+ for (Stmt::const_child_range I = S->children(); I; ++I)
if (const Stmt *child = *I)
if (containsStmt<T>(child))
return true;
static Expr::CanThrowResult CanSubExprsThrow(ASTContext &C, const Expr *CE) {
Expr *E = const_cast<Expr*>(CE);
Expr::CanThrowResult R = Expr::CT_Cannot;
- Expr::child_iterator I, IE;
- for (llvm::tie(I, IE) = E->children();
- I != IE && R != Expr::CT_Can; ++I) {
+ for (Expr::child_range I = E->children(); I && R != Expr::CT_Can; ++I) {
R = MergeCanThrow(R, cast<Expr>(*I)->CanThrow(C));
}
return R;
this->Designators = new (C) Designator[NumDesignators];
// Record the initializer itself.
- child_iterator Child = child_begin();
+ child_range Child = children();
*Child++ = Init;
// Copy the designators and their subexpressions, computing
typedef llvm::DenseMap<Stmt*, Stmt*> MapTy;
static void BuildParentMap(MapTy& M, Stmt* S) {
- for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
+ for (Stmt::child_range I = S->children(); I; ++I)
if (*I) {
M[*I] = S;
BuildParentMap(M, *I);
Visit(S);
// Print out children.
- Stmt::child_iterator CI = S->child_begin(), CE = S->child_end();
- if (CI != CE) {
- while (CI != CE) {
+ Stmt::child_range CI = S->children();
+ if (CI) {
+ while (CI) {
OS << '\n';
DumpSubTree(*CI++);
}
void StmtProfiler::VisitStmt(Stmt *S) {
ID.AddInteger(S->getStmtClass());
- for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end();
- C != CEnd; ++C)
+ for (Stmt::child_range C = S->children(); C; ++C)
Visit(*C);
}
}
void VisitStmt(Stmt *S) {
- for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();I!=E;++I)
+ for (Stmt::child_range I = S->children(); I; ++I)
if (Stmt *child = *I)
Visit(child);
}
/// VisitChildren - Visit the children of a Stmt.
CFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) {
CFGBlock *B = Block;
- for (Stmt::child_iterator I = Terminator->child_begin(),
- E = Terminator->child_end(); I != E; ++I) {
+ for (Stmt::child_range I = Terminator->children(); I; ++I) {
if (*I) B = Visit(*I);
}
return B;
// them in helper vector.
typedef llvm::SmallVector<Stmt *, 4> ChildrenVect;
ChildrenVect ChildrenRev;
- for (Stmt::child_iterator I = E->child_begin(), L = E->child_end();
- I != L; ++I) {
+ for (Stmt::child_range I = E->children(); I; ++I) {
if (*I) ChildrenRev.push_back(*I);
}
if (!S)
return;
- for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) {
+ for (Stmt::child_range I = S->children(); I; ++I) {
Stmt *child = *I;
if (!child)
continue;
if (StmtExpr* SE = dyn_cast<StmtExpr>(S)) {
CompoundStmt* Sub = SE->getSubStmt();
- if (Sub->child_begin() != Sub->child_end()) {
+ if (Sub->children()) {
OS << "({ ... ; ";
Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
OS << " })\n";
} // switch (head->getStmtClass())
// Add all substatements to the worklist
- for (Stmt::const_child_iterator I = Head->child_begin(),
- E = Head->child_end(); I != E; ++I)
+ for (Stmt::const_child_range I = Head->children(); I; ++I)
if (*I)
WorkList.push_back(*I);
} // while (!WorkList.empty())
// We don't stop at the first subexpression that is Uninitialized because
// evaluating some subexpressions may result in propogating "Uninitialized"
// or "Initialized" to variables referenced in the other subexpressions.
- for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
+ for (Stmt::child_range I = S->children(); I; ++I)
if (*I && Visit(*I) == Uninitialized) x = Uninitialized;
return x;
IgnoreCaseStmts = true;
// Scan subexpressions for verboten labels.
- for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
- I != E; ++I)
+ for (Stmt::const_child_range I = S->children(); I; ++I)
if (ContainsLabel(*I, IgnoreCaseStmts))
return true;
Doc.PrintDecl(*DI);
}
} else {
- for (Stmt::child_iterator i = S->child_begin(), e = S->child_end();
- i != e; ++i)
+ for (Stmt::child_range i = S->children(); i; ++i)
DumpSubTree(*i);
}
Doc.toParent();
}
void VisitStmt(Stmt *Node) {
- for (Stmt::child_iterator
- I = Node->child_begin(), E = Node->child_end(); I != E; ++I)
+ for (Stmt::child_range I = Node->children(); I; ++I)
if (*I)
Visit(*I);
}
void VisitCallExpr(CallExpr *CE);
void VisitChildren(Stmt *S) {
- for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)
+ for (Stmt::child_range I = S->children(); I; ++I)
if (*I)
static_cast<CGBuilder*>(this)->Visit(*I);
}
}
Stmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) {
- for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
- CI != E; ++CI) {
+ for (Stmt::child_range CI = S->children(); CI; ++CI) {
if (*CI) {
Stmt *newStmt = RewriteObjCNestedIvarRefExpr(*CI, replaced);
if (newStmt)
void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
{
// Perform a bottom up traversal of all children.
- for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
- CI != E; ++CI)
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
if (*CI)
WarnAboutReturnGotoStmts(*CI);
void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
{
// Perform a bottom up traversal of all children.
- for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
- CI != E; ++CI)
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
if (*CI)
HasReturnStmts(*CI, hasReturns);
void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
// Perform a bottom up traversal of all children.
- for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
- CI != E; ++CI)
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
if (*CI) {
RewriteTryReturnStmts(*CI);
}
void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
// Perform a bottom up traversal of all children.
- for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
- CI != E; ++CI)
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
if (*CI) {
RewriteSyncReturnStmts(*CI, syncExitBuf);
}
}
void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
- for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
- CI != E; ++CI)
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
if (*CI) {
if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
GetBlockDeclRefExprs(CBE->getBody());
void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs,
llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) {
- for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
- CI != E; ++CI)
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
if (*CI) {
if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
// we get this right.
void RewriteObjC::CollectPropertySetters(Stmt *S) {
// Perform a bottom up traversal of all children.
- for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
- CI != E; ++CI)
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
if (*CI)
CollectPropertySetters(*CI);
SourceRange OrigStmtRange = S->getSourceRange();
// Perform a bottom up rewrite of all children.
- for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
- CI != E; ++CI)
+ for (Stmt::child_range CI = S->children(); CI; ++CI)
if (*CI) {
Stmt *newStmt;
Stmt *S = (*CI);
break;
}
- for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E;
- ++CI) {
+ for (Stmt::child_range CI = S->children(); CI; ++CI) {
if (SkipFirstSubStmt) {
SkipFirstSubStmt = false;
continue;
// Now just recurse over the expression's children.
CC = E->getExprLoc();
- for (Stmt::child_iterator I = E->child_begin(), IE = E->child_end();
- I != IE; ++I)
+ for (Stmt::child_range I = E->children(); I; ++I)
AnalyzeImplicitConversions(S, cast<Expr>(*I), CC);
}
/// VisitExpr - Visit all of the children of this expression.
bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) {
bool IsInvalid = false;
- for (Stmt::child_iterator I = Node->child_begin(),
- E = Node->child_end(); I != E; ++I)
+ for (Stmt::child_range I = Node->children(); I; ++I)
IsInvalid |= Visit(*I);
return IsInvalid;
}
if (UOE->getOpcode() == UO_AddrOf)
return false;
}
- for (Stmt::const_child_iterator it = S->child_begin(), e = S->child_end();
- it != e; ++it) {
+ for (Stmt::const_child_range it = S->children(); it; ++it) {
if (!*it) {
// An expression such as 'member(arg ?: "")' may trigger this.
continue;
}
static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
- for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E;
- ++CI) {
+ for (Stmt::child_range CI = S->children(); CI; ++CI) {
Stmt *SubStmt = *CI;
if (!SubStmt)
continue;
}
void EnqueueVisitor::EnqueueChildren(Stmt *S) {
unsigned size = WL.size();
- for (Stmt::child_iterator Child = S->child_begin(), ChildEnd = S->child_end();
- Child != ChildEnd; ++Child) {
+ for (Stmt::child_range Child = S->children(); Child; ++Child) {
AddStmt(*Child);
}
if (size == WL.size())