Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision c5f69fd69f8643b17092381eda9da1da5bf21f5c)
+++ src/AST/Fwd.hpp	(revision fca78f10fcf2198f57e0f9e7ea3fe351ee91befa)
@@ -49,4 +49,5 @@
 class WhileDoStmt;
 class ForStmt;
+class ForeachStmt;
 class SwitchStmt;
 class CaseClause;
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision c5f69fd69f8643b17092381eda9da1da5bf21f5c)
+++ src/AST/Pass.hpp	(revision fca78f10fcf2198f57e0f9e7ea3fe351ee91befa)
@@ -138,4 +138,5 @@
 	const ast::Stmt *             visit( const ast::WhileDoStmt          * ) override final;
 	const ast::Stmt *             visit( const ast::ForStmt              * ) override final;
+	const ast::Stmt *             visit( const ast::ForeachStmt          * ) override final;
 	const ast::Stmt *             visit( const ast::SwitchStmt           * ) override final;
 	const ast::CaseClause *       visit( const ast::CaseClause           * ) override final;
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision c5f69fd69f8643b17092381eda9da1da5bf21f5c)
+++ src/AST/Pass.impl.hpp	(revision fca78f10fcf2198f57e0f9e7ea3fe351ee91befa)
@@ -803,7 +803,25 @@
 		maybe_accept_top( node, &ForStmt::cond  );
 		maybe_accept_top( node, &ForStmt::inc   );
-		maybe_accept_top( node, &ForStmt::range_over );
 		maybe_accept_as_compound( node, &ForStmt::body  );
 		maybe_accept_as_compound( node, &ForStmt::else_ );
+	}
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// ForeachStmt
+template< typename core_t >
+const ast::Stmt * ast::Pass< core_t >::visit( const ast::ForeachStmt * node ) {
+	VISIT_START( node );
+
+	if ( __visit_children() ) {
+		// for statements introduce a level of scope (for the initialization)
+		guard_symtab guard { *this };
+		// xxx - old ast does not create WithStmtsToAdd scope for loop inits. should revisit this later.
+		maybe_accept( node, &ForeachStmt::inits );
+		maybe_accept_top( node, &ForeachStmt::range );
+		maybe_accept_as_compound( node, &ForeachStmt::body  );
+		maybe_accept_as_compound( node, &ForeachStmt::else_ );
 	}
 
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision c5f69fd69f8643b17092381eda9da1da5bf21f5c)
+++ src/AST/Print.cpp	(revision fca78f10fcf2198f57e0f9e7ea3fe351ee91befa)
@@ -637,4 +637,52 @@
 	}
 
+	virtual const ast::Stmt * visit( const ast::ForeachStmt * node ) override final {
+		os << "Range for Statement" << endl;
+
+		if ( ! node->inits.empty() ) {
+			os << indent << "... initialization:" << endl;
+			++indent;
+			for ( const ast::Stmt * stmt : node->inits ) {
+				os << indent+1;
+				safe_print( stmt );
+			}
+			--indent;
+		}
+
+		if ( node->isIncreasing ) {
+			os << indent << "increasing" << endl;
+		} else {
+			os << indent << "decreasing" << endl;
+		}
+
+		if ( !node->range ) {
+			os << indent << "... over range:" << endl;
+			++indent;
+			node->range->accept( *this );
+			--indent;
+		}
+
+		if ( node->body ) {
+			os << indent << "... with body:" << endl;
+			++indent;
+			os << indent;
+			node->body->accept( *this );
+			--indent;
+		}
+
+		if ( node->else_ ) {
+			os << indent << "... with else:" << endl;
+			++indent;
+			os << indent;
+			node->else_->accept( *this );
+			--indent;
+		}
+
+		os << endl;
+		print( node->labels );
+
+		return node;
+	}
+
 	virtual const ast::Stmt * visit( const ast::SwitchStmt * node ) override final {
 		os << "Switch on condition: ";
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision c5f69fd69f8643b17092381eda9da1da5bf21f5c)
+++ src/AST/Stmt.hpp	(revision fca78f10fcf2198f57e0f9e7ea3fe351ee91befa)
@@ -237,6 +237,4 @@
 	ptr<Expr> cond;
 	ptr<Expr> inc;
-	ptr<Expr> range_over;
-	bool is_inc;
 	ptr<Stmt> body;
 	ptr<Stmt> else_;
@@ -245,14 +243,9 @@
 			 const Expr * inc, const Stmt * body, const std::vector<Label> && label = {} )
 		: Stmt(loc, std::move(label)), inits(std::move(inits)), cond(cond), inc(inc),
-			range_over(nullptr), body(body), else_(nullptr) {}
+		body(body), else_(nullptr) {}
 
 	ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond,
 			 const Expr * inc, const Stmt * body, const Stmt * else_, const std::vector<Label> && labels = {} )
 		: Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), inc(inc),
-			range_over(nullptr), body(body), else_(else_) {}
-
-	ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * range_over, bool is_inc,
-			 const Stmt * body, const Stmt * else_ )
-		: Stmt(loc, std::move(labels)), inits(std::move(inits)), range_over(range_over), is_inc(is_inc), 
 		body(body), else_(else_) {}
 
@@ -260,4 +253,27 @@
   private:
 	ForStmt * clone() const override { return new ForStmt{ *this }; }
+	MUTATE_FRIEND
+};
+
+enum RangeDirection { DecreasingRange, IncreasingRange };
+
+// For-each loop: for (... : ...) ... else ...
+class ForeachStmt final : public Stmt {
+  public:
+	std::vector<ptr<Stmt>> inits;
+	ptr<Expr> range;
+	ptr<Stmt> body;
+	ptr<Stmt> else_;
+	// This is a property of the range, but there is no place to store it.
+	RangeDirection isIncreasing;
+
+	ForeachStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits,
+			const Expr * range_over, RangeDirection isInc, const Stmt * body, const Stmt * else_ )
+		: Stmt(loc, std::move(labels)), inits(std::move(inits)), range(range_over),
+		body(body), else_(else_), isIncreasing(isInc) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
+	ForeachStmt * clone() const override { return new ForeachStmt{ *this }; }
 	MUTATE_FRIEND
 };
Index: src/AST/Visitor.hpp
===================================================================
--- src/AST/Visitor.hpp	(revision c5f69fd69f8643b17092381eda9da1da5bf21f5c)
+++ src/AST/Visitor.hpp	(revision fca78f10fcf2198f57e0f9e7ea3fe351ee91befa)
@@ -41,4 +41,5 @@
     virtual const ast::Stmt *             visit( const ast::WhileDoStmt          * ) = 0;
     virtual const ast::Stmt *             visit( const ast::ForStmt              * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::ForeachStmt          * ) = 0;
     virtual const ast::Stmt *             visit( const ast::SwitchStmt           * ) = 0;
     virtual const ast::CaseClause *       visit( const ast::CaseClause           * ) = 0;
