Index: src/Common/GC.cc
===================================================================
--- src/Common/GC.cc	(revision 6f81db35825e78019dce3cfedb438bf266676fe9)
+++ src/Common/GC.cc	(revision 24de7b1695ec2b0f72713eb9c21700d888488dde)
@@ -40,5 +40,5 @@
 }
 
-const GC& GC::operator<< (const GC_Traceable* obj) const {
+const GC& GC::operator<< (const GC_Object* obj) const {
 	if( obj )
 	{
@@ -119,4 +119,12 @@
 }
 
+GC_Object::GC_Object( const GC_Object& ) {
+	GC::get().register_object( this );
+}
+
+GC_Object::GC_Object( GC_Object&& ) {
+	GC::get().register_object( this );
+}
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/Common/GC.h
===================================================================
--- src/Common/GC.h	(revision 6f81db35825e78019dce3cfedb438bf266676fe9)
+++ src/Common/GC.h	(revision 24de7b1695ec2b0f72713eb9c21700d888488dde)
@@ -18,5 +18,4 @@
 #include <vector>
 
-class GC_Traceable;
 class GC_Object;
 class BaseSyntaxNode;
@@ -30,5 +29,5 @@
 
 	/// Traces a traceable object
-	const GC& operator<< (const GC_Traceable*) const;
+	const GC& operator<< (const GC_Object*) const;
 
 	/// Adds a new object to garbage collection
@@ -111,21 +110,26 @@
 }
 
-/// Class that is traced by the GC, but not managed by it
-class GC_Traceable {
+/// Class that is managed by the GC
+class GC_Object {
 	friend class GC;
 protected:
 	mutable bool mark;
 
+	// Override default constructors to ensure clones are registered and properly marked
+	GC_Object();
+
+	GC_Object(const GC_Object&);
+
+	GC_Object(GC_Object&&);
+
+	GC_Object& operator= (const GC_Object&) { /* do not assign mark */ return *this; }
+
+	GC_Object& operator= (GC_Object&&) { /* do not assign mark */ return *this; }
+
+	// Ensure subclasses can be deleted by garbage collector
+	virtual ~GC_Object() {}
+
 	/// override to trace any child objects
 	virtual void trace(const GC&) const {}
-};
-
-/// Class that is managed by the GC
-class GC_Object : public GC_Traceable {
-	friend class GC;
-protected:
-	virtual ~GC_Object() {}
-public:
-	GC_Object();
 };
 
Index: src/SynTree/GcTracer.h
===================================================================
--- src/SynTree/GcTracer.h	(revision 6f81db35825e78019dce3cfedb438bf266676fe9)
+++ src/SynTree/GcTracer.h	(revision 24de7b1695ec2b0f72713eb9c21700d888488dde)
@@ -38,10 +38,8 @@
 	void previsit( BaseSyntaxNode * node ) {
 		// skip tree if already seen
-		// xxx - this should be uncommented (it breaks object cycles), but at the moment it seems 
-		// like the object cycles don't happen and other bugs do
-		// if ( node->mark == gc.mark ) {
-		// 	visit_children = false;
-		// 	return;
-		// }
+		if ( node->mark == gc.mark ) {
+			visit_children = false;
+			return;
+		}
 
 		// mark node
@@ -50,4 +48,8 @@
 
 	// add visits left out by PassVisitor
+
+	void postvisit( Constant* con ) {
+		maybeAccept( con->get_type(), *visitor );
+	}
 
 	void postvisit( Expression* expr ) {
@@ -58,4 +60,9 @@
 		postvisit( static_cast<Expression*>(expr) );
 		maybeAccept( expr->function, *visitor );
+	}
+
+	void postvisit( VariableExpr* expr ) {
+		postvisit( static_cast<Expression*>(expr) );
+		maybeAccept( expr->var, *visitor );  // not in PassVisitor because it causes cycle
 	}
 
