Index: src/Validate/Autogen.cpp
===================================================================
--- src/Validate/Autogen.cpp	(revision 59c8dff49bbb5284b39ab27da894a644327a531a)
+++ src/Validate/Autogen.cpp	(revision f988834af650698a46072a2a91bb190224a866bd)
@@ -445,5 +445,7 @@
 
 		auto * paramType = ast::deepCopy( member->get_type() );
-		paramType->attributes.clear();
+		erase_if( paramType->attributes, []( ast::Attribute const * attr ){
+			return !attr->isValidOnFuncParam();
+		} );
 		ast::ObjectDecl * param = new ast::ObjectDecl(
 			getLocation(), member->name, paramType );
Index: src/Validate/ReplaceTypedef.cpp
===================================================================
--- src/Validate/ReplaceTypedef.cpp	(revision 59c8dff49bbb5284b39ab27da894a644327a531a)
+++ src/Validate/ReplaceTypedef.cpp	(revision f988834af650698a46072a2a91bb190224a866bd)
@@ -25,16 +25,4 @@
 
 namespace {
-
-bool isNonParameterAttribute( ast::Attribute const * attr ) {
-	static const std::vector<std::string> bad_names = {
-		"aligned", "__aligned__",
-	};
-	for ( auto name : bad_names ) {
-		if ( name == attr->name ) {
-			return true;
-		}
-	}
-	return false;
-}
 
 struct ReplaceTypedefCore final :
@@ -101,5 +89,7 @@
 		// by typedef. GCC appears to do the same thing.
 		if ( isAtFunctionTop ) {
-			erase_if( ret->attributes, isNonParameterAttribute );
+			erase_if( ret->attributes, []( ast::Attribute const * attr ){
+				return !attr->isValidOnFuncParam();
+			} );
 		}
 		for ( const auto & attribute : type->attributes ) {
