Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision f1b1e4c22ee1c825678ab38142bbcf3879708434)
+++ src/SynTree/Declaration.h	(revision 2f6b7c9cc761b794c66ba5ff95d6a88b646e5d30)
@@ -115,17 +115,5 @@
 	typedef DeclarationWithType Parent;
   public:
-	// temporary - merge this into general GCC attributes
-	struct Attribute {
-		enum Type {
-			NoAttribute, Constructor, Destructor,
-		} type;
-		enum Priority {
-			// priorities 0-100 are reserved by gcc, so it's okay to use 100 an exceptional case
-			Default = 100, High,
-		} priority;
-		Attribute(Type t = NoAttribute, Priority p = Default) : type(t), priority(p) {};
-	};
-
-	FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, Attribute attribute = Attribute() );
+	FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, const std::list< Attribute * > attributes = std::list< Attribute * >() );
 	FunctionDecl( const FunctionDecl &other );
 	virtual ~FunctionDecl();
@@ -140,6 +128,5 @@
 	std::list< std::string >& get_oldIdents() { return oldIdents; }
 	std::list< Declaration* >& get_oldDecls() { return oldDecls; }
-	Attribute get_attribute() const { return attribute; }
-	void set_attribute( Attribute newValue ) { attribute = newValue; }
+	std::list< Attribute * >& get_attributes() { return attributes; }
 
 	virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); }
@@ -153,5 +140,5 @@
 	std::list< std::string > oldIdents;
 	std::list< Declaration* > oldDecls;
-	Attribute attribute;
+	std::list< Attribute * > attributes;
 };
 
Index: src/SynTree/FunctionDecl.cc
===================================================================
--- src/SynTree/FunctionDecl.cc	(revision f1b1e4c22ee1c825678ab38142bbcf3879708434)
+++ src/SynTree/FunctionDecl.cc	(revision 2f6b7c9cc761b794c66ba5ff95d6a88b646e5d30)
@@ -19,8 +19,9 @@
 #include "Statement.h"
 #include "Type.h"
+#include "Attribute.h"
 #include "Common/utility.h"
 
-FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, Attribute attribute )
-		: Parent( name, sc, linkage ), type( type ), statements( statements ), attribute( attribute ) {
+FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, std::list< Attribute * > attributes )
+		: Parent( name, sc, linkage ), type( type ), statements( statements ), attributes( attributes ) {
 	set_isInline( isInline );
 	set_isNoreturn( isNoreturn );
@@ -32,5 +33,6 @@
 
 FunctionDecl::FunctionDecl( const FunctionDecl &other )
-	: Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ), attribute( other.attribute ) {
+	: Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ) {
+		cloneAll( other.attributes, attributes );
 }
 
@@ -38,4 +40,5 @@
 	delete type;
 	delete statements;
+	deleteAll( attributes );
 }
 
@@ -65,17 +68,7 @@
 		os << "_Noreturn ";
 	} // if
-	switch ( attribute.type ) {
-		case Attribute::Constructor:
-			os << "Global Constructor ";
-			break;
-		case Attribute::Destructor:
-			os << "Global Destructor ";
-			break;
-		default:
-			break;
-	}
-	if ( attribute.priority != Attribute::Default ) {
-		os << "with priority " << attribute.priority << " ";
-	}
+
+	printAll( attributes, os, indent );
+
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
 		os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
@@ -118,17 +111,7 @@
 		os << "_Noreturn ";
 	} // if
-	switch ( attribute.type ) {
-		case Attribute::Constructor:
-			os << " Global Constructor ";
-			break;
-		case Attribute::Destructor:
-			os << " Global Destructor ";
-			break;
-		default:
-			break;
-	}
-	if ( attribute.priority != Attribute::Default ) {
-		os << "with priority " << attribute.priority << " ";
-	}
+
+	// xxx - should printShort print attributes?
+
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
 		os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision f1b1e4c22ee1c825678ab38142bbcf3879708434)
+++ src/SynTree/SynTree.h	(revision 2f6b7c9cc761b794c66ba5ff95d6a88b646e5d30)
@@ -118,4 +118,7 @@
 class TypeSubstitution;
 
+// gcc attribute
+class Attribute;
+
 #endif // SYNTREE_H
 
Index: src/SynTree/module.mk
===================================================================
--- src/SynTree/module.mk	(revision f1b1e4c22ee1c825678ab38142bbcf3879708434)
+++ src/SynTree/module.mk	(revision 2f6b7c9cc761b794c66ba5ff95d6a88b646e5d30)
@@ -6,5 +6,5 @@
 ## file "LICENCE" distributed with Cforall.
 ##
-## module.mk -- 
+## module.mk --
 ##
 ## Author           : Richard C. Bilson
@@ -46,4 +46,5 @@
        SynTree/Visitor.cc \
        SynTree/Mutator.cc \
-       SynTree/TypeSubstitution.cc
+       SynTree/TypeSubstitution.cc \
+       SynTree/Attribute.cc
 
