Index: src/AST/AssertAcyclic.cpp
===================================================================
--- src/AST/AssertAcyclic.cpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
+++ src/AST/AssertAcyclic.cpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -0,0 +1,51 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// AssertAcyclic.cpp -- Check that ast::ptr does not form a cycle.
+//
+// Author           : Andrew Beach
+// Created On       : Thu Jun 06 15:00:00 2019
+// Last Modified By : Andrew Beach
+// Last Modified On : Thu Jun 06 15:00:00 2019
+// Update Count     : 0
+//
+
+#include "AssertAcyclic.hpp"
+
+#include "AST/Pass.hpp"
+
+namespace {
+
+class NoStrongCyclesCore : public ast::WithGuards {
+    std::vector<const ast::Node *> parents;
+public:
+	void previsit ( const ast::Node * node ) {
+		for (auto & p : parents) {
+			assert(p != node);
+		}
+		parents.push_back(node);
+		GuardAction( [this]() { parents.pop_back(); } );
+	}
+};
+
+}
+
+namespace ast {
+
+void assertAcyclic( const std::list< ast::ptr< ast::Decl > > translationUnit ) {
+   	Pass<NoStrongCyclesCore> visitor;
+	for ( auto & decl : translationUnit ) {
+		decl->accept( visitor );
+	}
+}
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/AssertAcyclic.hpp
===================================================================
--- src/AST/AssertAcyclic.hpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
+++ src/AST/AssertAcyclic.hpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -0,0 +1,35 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// AssertAcyclic.hpp -- Check that ast::ptr does not form a cycle.
+//
+// Author           : Andrew Beach
+// Created On       : Thr May 6 15:00:00 2019
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr May 6 15:00:00 2019
+// Update Count     : 0
+//
+
+#pragma once
+
+#include <list>
+
+#include "Node.hpp"
+namespace ast {
+    class Decl;
+};
+
+namespace ast {
+
+void assertAcyclic( const std::list< ast::ptr< ast::Decl > > translationUnit );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 0b73f0cd5f12dd95097dbdf9ad89a93ff3d695da)
+++ src/AST/Node.hpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -18,4 +18,5 @@
 #include <cassert>
 #include <iosfwd>
+#include <type_traits> // for remove_reference
 
 #include "Common/ErrorObjects.h"  // for SemanticErrorException
@@ -82,6 +83,6 @@
 };
 
-// Mutate a node, non-member function to avoid static type
-// problems and be able to use auto return
+/// Mutate a node, non-member function to avoid static type
+/// problems and be able to use auto return
 template<typename node_t>
 node_t * mutate( const node_t * node ) {
@@ -95,4 +96,18 @@
 	);
 	return node->clone();
+}
+
+/// Mutate a node field (only clones if not equal to existing value)
+template<typename node_t, typename field_t>
+const node_t * mutate_field( 
+	const node_t * node, 
+	typename std::remove_const<typename std::remove_reference<field_t>::type>::type node_t::* field,
+	field_t&& val 
+) {
+	if ( node->*field == val ) return node;
+	
+	node_t * ret = mutate( node );
+	ret->*field = std::forward< field_t >( val );
+	return ret;
 }
 
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 0b73f0cd5f12dd95097dbdf9ad89a93ff3d695da)
+++ src/AST/Pass.hpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -201,4 +201,5 @@
 	container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
 
+public:
 	/// Logic to call the accept and mutate the parent if needed, delegates call to accept
 	template<typename node_t, typename parent_t, typename child_t>
Index: src/AST/module.mk
===================================================================
--- src/AST/module.mk	(revision 0b73f0cd5f12dd95097dbdf9ad89a93ff3d695da)
+++ src/AST/module.mk	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -16,4 +16,5 @@
 
 SRC_AST = \
+	AST/AssertAcyclic.cpp \
 	AST/Attribute.cpp \
 	AST/Convert.cpp \
