Index: src/CodeGen/LinkOnce.cc
===================================================================
--- src/CodeGen/LinkOnce.cc	(revision cf34e82e233faaa9343ac3f85950003f225fd94f)
+++ src/CodeGen/LinkOnce.cc	(revision 3cbe3208a46cac04121664ab55595e2679b6dcb3)
@@ -10,6 +10,6 @@
 // Created On       : Thur May 13 10:10:00 2021
 // Last Modified By : Andrew Beach
-// Last Modified On : Thur May 13 14:39:00 2021
-// Update Count     : 0
+// Last Modified On : Wed Oct  4 10:52:00 2023
+// Update Count     : 1
 //
 
@@ -18,13 +18,19 @@
 #include <algorithm>
 
+#include "AST/Attribute.hpp"
+#include "AST/Decl.hpp"
+#include "AST/Expr.hpp"
+#include "AST/Pass.hpp"
 #include "Common/PassVisitor.h"       // for PassVisitor, WithShortCircuiting
 
 namespace CodeGen {
 
-static bool is_cfa_linkonce( Attribute const * attr ) {
+namespace {
+
+bool is_cfa_linkonce_old( Attribute const * attr ) {
 	return std::string("cfa_linkonce") == attr->name;
 }
 
-static bool is_section_attribute( Attribute const * attr ) {
+bool is_section_attribute_old( Attribute const * attr ) {
 	return std::string("section") == attr->name;
 }
@@ -39,8 +45,8 @@
 		std::list< Attribute * > & attributes = decl->attributes;
 		// See if we can find the element:
-		auto found = std::find_if(attributes.begin(), attributes.end(), is_cfa_linkonce );
+		auto found = std::find_if(attributes.begin(), attributes.end(), is_cfa_linkonce_old );
 		if ( attributes.end() != found ) {
 			// Remove any other sections:
-			attributes.remove_if( is_section_attribute );
+			attributes.remove_if( is_section_attribute_old );
 			// Iterator to the cfa_linkonce attribute should still be valid.
 			Attribute * attribute = *found;
@@ -63,4 +69,57 @@
 };
 
+bool is_cfa_linkonce( ast::Attribute const * attr ) {
+	return "cfa_linkonce" == attr->name;
+}
+
+bool is_section_attribute( ast::Attribute const * attr ) {
+	return "section" == attr->name;
+}
+
+struct LinkOnceCore : public ast::WithShortCircuiting {
+	void previsit( ast::Decl const * ) {
+		visit_children = false;
+	}
+
+	ast::DeclWithType const * postvisit( ast::DeclWithType const * decl ) {
+		// Check to see if we have to mutate, because should be uncommon.
+		{
+			auto & attributes = decl->attributes;
+			auto found = std::find_if( attributes.begin(), attributes.end(),
+					is_cfa_linkonce );
+			if ( attributes.end() == found ) return decl;
+		}
+		auto mutDecl = mutate( decl );
+		auto & attributes = mutDecl->attributes;
+
+		// Remove all conflicting section attributes.
+		erase_if( attributes, is_section_attribute );
+
+		// Get the attribute, and overwrite it as a section attribute.
+		auto found = std::find_if( attributes.begin(), attributes.end(),
+				is_cfa_linkonce );
+		assert( attributes.end() != found );
+		ast::Attribute * attribute = found->get_and_mutate();
+		assert( attribute->params.empty() );
+		assert( !decl->mangleName.empty() );
+
+		attribute->name = "section";
+		attribute->params.push_back(
+			ast::ConstantExpr::from_string( mutDecl->location,
+				".gnu.linkonce." + decl->mangleName
+			)
+		);
+
+		// Unconditionnaly add "visibility(default)" to anything with
+		// .gnu.linkonce visibility is a mess otherwise.
+		attributes.push_back( new ast::Attribute( "visibility", {
+			ast::ConstantExpr::from_string( mutDecl->location, "default" )
+		} ) );
+		return mutDecl;
+	}
+};
+
+} // namespace
+
 void translateLinkOnce( std::list< Declaration *> & translationUnit ) {
 	PassVisitor<LinkOnceVisitorCore> translator;
@@ -68,3 +127,7 @@
 }
 
+void translateLinkOnce( ast::TranslationUnit & translationUnit ) {
+	ast::Pass<LinkOnceCore>::run( translationUnit );
 }
+
+} // namespace CodeGen
Index: src/CodeGen/LinkOnce.h
===================================================================
--- src/CodeGen/LinkOnce.h	(revision cf34e82e233faaa9343ac3f85950003f225fd94f)
+++ src/CodeGen/LinkOnce.h	(revision 3cbe3208a46cac04121664ab55595e2679b6dcb3)
@@ -10,6 +10,6 @@
 // Created On       : Thur May 13 10:06:00 2021
 // Last Modified By : Andrew Beach
-// Last Modified On : Thur May 13 14:38:00 2021
-// Update Count     : 0
+// Last Modified On : Wed Oct  4 10:52:00 2023
+// Update Count     : 1
 //
 
@@ -23,8 +23,12 @@
 
 class Declaration;
+namespace ast {
+	class TranslationUnit;
+}
 
 namespace CodeGen {
 
 void translateLinkOnce( std::list< Declaration *> & translationUnit );
+void translateLinkOnce( ast::TranslationUnit & translationUnit );
 /* Convert the cfa_linkonce attribute on top level declaration into
  * a special section declaration (.gnu.linkonce) so that it may be defined
Index: src/main.cc
===================================================================
--- src/main.cc	(revision cf34e82e233faaa9343ac3f85950003f225fd94f)
+++ src/main.cc	(revision 3cbe3208a46cac04121664ab55595e2679b6dcb3)
@@ -421,8 +421,7 @@
 		DUMP( bboxp, std::move( transUnit ) );
 		PASS( "Box", GenPoly::box, transUnit );
+		PASS( "Link-Once", CodeGen::translateLinkOnce, transUnit );
 
 		translationUnit = convert( std::move( transUnit ) );
-
-		PASS( "Link-Once", CodeGen::translateLinkOnce, translationUnit );
 
 		// Code has been lowered to C, now we can start generation.
