Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/CodeGen/CodeGenerator.cc	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -9,5 +9,5 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : 
+// Last Modified By :
 // Last Modified On : Sun Jul 31 08:42:18 2016
 // Update Count     : 345
@@ -148,4 +148,6 @@
 	void CodeGenerator::visit( ObjectDecl *objectDecl ) {
 		extension( objectDecl );
+		genAttributes( objectDecl->get_attributes() );
+
 		handleStorageClass( objectDecl );
 		output << genType( objectDecl->get_type(), mangleName( objectDecl ) );
Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/InitTweak/FixGlobalInit.cc	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -107,5 +107,5 @@
 
 			Statement * dtor = ctorInit->get_dtor();
-			if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
+			if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
 				// don't need to call intrinsic dtor, because it does nothing, but
 				// non-intrinsic dtors must be called
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/InitTweak/FixInit.cc	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -26,4 +26,5 @@
 #include "SynTree/Type.h"
 #include "SynTree/Expression.h"
+#include "SynTree/Attribute.h"
 #include "SynTree/Statement.h"
 #include "SynTree/Initializer.h"
@@ -208,7 +209,5 @@
 				try {
 					*i = maybeMutate( *i, fixer );
-					// if (! fixer.staticDtorDecls.empty() ) {
-						translationUnit.splice( i, fixer.staticDtorDecls );
-					// }
+					translationUnit.splice( i, fixer.staticDtorDecls );
 				} catch( SemanticError &e ) {
 					errors.append( e );
@@ -446,44 +445,24 @@
 					if ( objDecl->get_storageClass() == DeclarationNode::Static ) {
 						// originally wanted to take advantage of gcc nested functions, but
-						// we get memory errors with this approach. To remedy this, create a
-						// global static pointer that is set to refer to the object and make
-						// the dtor-caller function global so that.
+						// we get memory errors with this approach. To remedy this, the static
+						// variable is hoisted when the destructor needs to be called.
 						//
 						// generate:
-						// T * __objName_static_ptrN;
+						// static T __objName_static_varN;
 						// void __objName_dtor_atexitN() {
-						//   __dtor(__objName_static_ptrN);
+						//   __dtor__...;
 						// }
 						// int f(...) {
 						//   ...
-						//   static T __objName;
 						//   static bool __objName_uninitialized = true;
 						//   if (__objName_uninitialized) {
-						//     __objName_ptr = &__objName;
 						//     __ctor(__objName);
-						//     on_exit(__objName_dtor_atexitN, &__objName);
 						//     __objName_uninitialized = false;
+						//     atexit(__objName_dtor_atexitN);
 						//   }
 						//   ...
 						// }
 
-						static UniqueName ptrNamer( "_static_ptr" );
 						static UniqueName dtorCallerNamer( "_dtor_atexit" );
-
-						// T * __objName_ptrN
-						ObjectDecl * objPtr = new ObjectDecl( objDecl->get_mangleName() + ptrNamer.newName(), DeclarationNode::Static, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), objDecl->get_type()->clone() ), 0 );
-						objPtr->fixUniqueId();
-
-						// void __objName_dtor_atexitN(...) {...}
-						// need to modify dtor call so that it refers to objPtr, since function will be global
-						Statement * dtorStmt = ctorInit->get_dtor()->clone();
-						ApplicationExpr * dtor = dynamic_cast< ApplicationExpr * >( InitTweak::getCtorDtorCall( dtorStmt ) );
-						assert( dtor );
-						delete dtor->get_args().front();
-						dtor->get_args().front() = new VariableExpr( objPtr );
-
-						FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
-						dtorCaller->fixUniqueId();
-						dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
 
 						// static bool __objName_uninitialized = true
@@ -493,13 +472,4 @@
 						isUninitializedVar->fixUniqueId();
 
-						// __objName_static_ptrN = &__objName;
-						UntypedExpr * ptrAssign = new UntypedExpr( new NameExpr( "?=?" ) );
-						ptrAssign->get_args().push_back( new VariableExpr( objPtr ) );
-						ptrAssign->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
-
-						// atexit(dtor_atexit);
-						UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
-						callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
-
 						// __objName_uninitialized = false;
 						UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) );
@@ -511,6 +481,4 @@
 						std::list< Statement * > & body = initStmts->get_kids();
 						body.push_back( ctor );
-						body.push_back( new ExprStmt( noLabels, ptrAssign ) );
-						body.push_back( new ExprStmt( noLabels, callAtexit ) );
 						body.push_back( new ExprStmt( noLabels, setTrue ) );
 
@@ -520,7 +488,42 @@
 						stmtsToAddAfter.push_back( ifStmt );
 
-						// add pointer and dtor caller decls to list of decls that will be added into global scope
-						staticDtorDecls.push_back( objPtr );
-						staticDtorDecls.push_back( dtorCaller );
+						if ( ctorInit->get_dtor() ) {
+							// if the object has a non-trivial destructor, have to
+							// hoist it and the object into the global space and
+							// call the destructor function with atexit.
+
+							Statement * dtorStmt = ctorInit->get_dtor()->clone();
+
+							// void __objName_dtor_atexitN(...) {...}
+							FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
+							dtorCaller->fixUniqueId();
+							dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
+
+							// atexit(dtor_atexit);
+							UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
+							callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
+
+							body.push_back( new ExprStmt( noLabels, callAtexit ) );
+
+							// hoist variable and dtor caller decls to list of decls that will be added into global scope
+							staticDtorDecls.push_back( objDecl );
+							staticDtorDecls.push_back( dtorCaller );
+
+							// need to rename object uniquely since it now appears
+							// at global scope and there could be multiple function-scoped
+							// static variables with the same name in different functions.
+							static UniqueName staticNamer( "_static_var" );
+							objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() );
+
+							objDecl->set_init( NULL );
+							ctorInit->set_ctor( NULL );
+							delete ctorInit;
+
+							// xxx - temporary hack: need to return a declaration, but want to hoist the current object out of this scope
+							// create a new object which is never used
+							static UniqueName dummyNamer( "_dummy" );
+							ObjectDecl * dummy = new ObjectDecl( dummyNamer.newName(), DeclarationNode::Static, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), 0, std::list< Attribute * >{ new Attribute("unused") } );
+							return dummy;
+						}
 					} else {
 						stmtsToAddAfter.push_back( ctor );
@@ -582,5 +585,5 @@
 					assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
 					Statement * dtor = ctorInit->get_dtor();
-					if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
+					if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
 						// don't need to call intrinsic dtor, because it does nothing, but
 						// non-intrinsic dtors must be called
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/InitTweak/GenInit.cc	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -172,7 +172,11 @@
 		// if in function, generate const size_t var
 		static UniqueName dimensionName( "_array_dim" );
+
+		// C doesn't allow variable sized arrays at global scope or for static variables,
+		// so don't hoist dimension.
+		if ( ! inFunction ) return;
+		if ( storageclass == DeclarationNode::Static ) return;
+
 		if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
-			if ( ! inFunction ) return;
-
 			if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
 
@@ -203,13 +207,4 @@
 		CtorDtor ctordtor;
 		mutateAll( translationUnit, ctordtor );
-	}
-
-	namespace {
-		Expression * makeCtorDtorExpr( std::string name, ObjectDecl * objDecl, std::list< Expression * > args ) {
-			UntypedExpr * expr = new UntypedExpr( new NameExpr( name ) );
-			expr->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
-			expr->get_args().splice( expr->get_args().end(), args );
-			return expr;
-		}
 	}
 
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/InitTweak/InitTweak.cc	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -5,4 +5,5 @@
 #include "SynTree/Initializer.h"
 #include "SynTree/Expression.h"
+#include "SynTree/Attribute.h"
 #include "GenPoly/GenPoly.h"
 
@@ -125,6 +126,10 @@
 
 	namespace {
+		/// given index i, dimension d, initializer init, and callExpr f, generates
+		///   if (i < d) f(..., init)
+		///   ++i;
+		/// so that only elements within the range of the array are constructed
 		template< typename OutIterator >
-		void dothething( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
+		void buildCallExpr( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
 			UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
 			cond->get_args().push_back( index->clone() );
@@ -148,11 +153,13 @@
 			Expression * dimension = *idx++;
 
+			// xxx - may want to eventually issue a warning here if we can detect
+			// that the number of elements exceeds to dimension of the array
 			if ( idx == idxEnd ) {
 				if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {
 					for ( Initializer * init : *listInit ) {
-						dothething( callExpr->clone(), index, dimension, init, out );
+						buildCallExpr( callExpr->clone(), index, dimension, init, out );
 					}
 				} else {
-					dothething( callExpr->clone(), index, dimension, init, out );
+					buildCallExpr( callExpr->clone(), index, dimension, init, out );
 				}
 			} else {
@@ -166,4 +173,7 @@
 					throw SemanticError( "unbalanced list initializers" );
 				}
+
+				static UniqueName targetLabel( "L__autogen__" );
+				Label switchLabel( targetLabel.newName(), 0, std::list< Attribute * >{ new Attribute("unused") } );
 				for ( Initializer * init : *listInit ) {
 					Expression * condition;
@@ -178,8 +188,10 @@
 					std::list< Statement * > stmts;
 					build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
+					stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) );
 					CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
 					branches.push_back( caseStmt );
 				}
 				*out++ = new SwitchStmt( noLabels, index->clone(), branches );
+				*out++ = new NullStmt( std::list<Label>{ switchLabel } );
 			}
 		}
@@ -194,14 +206,13 @@
 	Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
 		if ( ! init ) return NULL;
-		std::list< Statement * > results;
-		build( dst, indices.begin(), indices.end(), init, back_inserter( results ) );
-		assert( results.size() <= 1 );
-		if ( results.empty() ) {
+		CompoundStmt * block = new CompoundStmt( noLabels );
+		build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
+		if ( block->get_kids().empty() ) {
+			delete block;
 			return NULL;
 		} else {
 			init = NULL; // init was consumed in creating the list init
-			return results.front();
-		}
-		return ! results.empty() ? results.front() : NULL;
+			return block;
+		}
 	}
 
@@ -280,5 +291,5 @@
 	}
 
-	bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
+	bool isIntrinsicSingleArgCallStmt( Statement * stmt ) {
 		std::list< Expression * > callExprs;
 		collectCtorDtorCalls( stmt, callExprs );
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/InitTweak/InitTweak.h	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -41,5 +41,5 @@
 	/// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
 	/// Currently has assertions that make it less than fully general.
-	bool isInstrinsicSingleArgCallStmt( Statement * expr );
+	bool isIntrinsicSingleArgCallStmt( Statement * expr );
 
 	/// get all Ctor/Dtor call expressions from a Statement
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/Parser/TypeData.cc	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -510,5 +510,5 @@
 		return buildVariable();
 	} else {
-		return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init, isInline, isNoreturn );
+		return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init, std::list< Attribute * >(),  isInline, isNoreturn );
 	} // if
 	return 0;
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/ResolvExpr/Resolver.cc	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -534,9 +534,16 @@
 		// implicitly generated, there's no way for it to have side effects, so get rid of it
 		// to clean up generated code.
-		if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
+		if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
 			delete ctorInit->get_ctor();
 			ctorInit->set_ctor( NULL );
 		}
-		if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_dtor() ) ) {
+
+		// xxx - todo
+		// if ( InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
+		// 	// can reduce the constructor down to a SingleInit using the
+		// 	// second argument from the ctor call
+		// }
+
+		if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_dtor() ) ) {
 			delete ctorInit->get_dtor();
 			ctorInit->set_dtor( NULL );
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/SymTab/Autogen.h	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -37,9 +37,10 @@
 	/// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
 	template< typename OutputIterator >
-	void genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
+	Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
 
 	/// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
+	/// optionally returns a statement which must be inserted prior to the containing loop, if there is one
 	template< typename OutputIterator >
-	void genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
+	Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
 		// want to be able to generate assignment, ctor, and dtor generically,
 		// so fname is either ?=?, ?{}, or ^?{}
@@ -63,15 +64,14 @@
 		fExpr->get_args().push_back( dstParam );
 
-    Statement * listInit = srcParam.buildListInit( fExpr );
-    if ( listInit ) {
-      *out++ = listInit;
-    }
+		Statement * listInit = srcParam.buildListInit( fExpr );
 
-    std::list< Expression * > args = *++srcParam;
-    fExpr->get_args().splice( fExpr->get_args().end(), args );
+		std::list< Expression * > args = *++srcParam;
+		fExpr->get_args().splice( fExpr->get_args().end(), args );
 
 		*out++ = new ExprStmt( noLabels, fExpr );
 
-    srcParam.clearArrayIndices();
+		srcParam.clearArrayIndices();
+
+		return listInit;
 	}
 
@@ -125,14 +125,7 @@
 		srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
 
-		// if ( srcParam ) {
-		// 	UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
-		// 	srcIndex->get_args().push_back( srcParam );
-		// 	srcIndex->get_args().push_back( new VariableExpr( index ) );
-		// 	srcParam = srcIndex;
-		// }
-
 		// for stmt's body, eventually containing call
 		CompoundStmt * body = new CompoundStmt( noLabels );
-		genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
+		Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
 
 		// block containing for stmt and index variable
@@ -140,4 +133,5 @@
 		CompoundStmt * block = new CompoundStmt( noLabels );
 		block->get_kids().push_back( new DeclStmt( noLabels, index ) );
+		if ( listInit ) block->get_kids().push_back( listInit );
 		block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
 
@@ -146,9 +140,10 @@
 
 	template< typename OutputIterator >
-	void genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
+	Statement * genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
 		if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
 			genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
+			return 0;
 		} else {
-			genScalarCall( srcParam, dstParam, fname, out, type, addCast );
+			return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
 		}
 	}
@@ -171,15 +166,15 @@
 		// currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
 		assert( stmts.size() <= 1 );
-    if ( stmts.size() == 1 ) {
-  		Statement * callStmt = stmts.front();
-  		if ( addCast ) {
-  			// implicitly generated ctor/dtor calls should be wrapped
-  			// so that later passes are aware they were generated.
-  			// xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
-  			// because this causes the address to be taken at codegen, which is illegal in C.
-  			callStmt = new ImplicitCtorDtorStmt( callStmt );
-  		}
-  		*out++ = callStmt;
-    }
+		if ( stmts.size() == 1 ) {
+			Statement * callStmt = stmts.front();
+			if ( addCast ) {
+				// implicitly generated ctor/dtor calls should be wrapped
+				// so that later passes are aware they were generated.
+				// xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
+				// because this causes the address to be taken at codegen, which is illegal in C.
+				callStmt = new ImplicitCtorDtorStmt( callStmt );
+			}
+			*out++ = callStmt;
+		}
 	}
 } // namespace SymTab
Index: src/SynTree/Declaration.cc
===================================================================
--- src/SynTree/Declaration.cc	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/SynTree/Declaration.cc	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Declaration.cc -- 
+// Declaration.cc --
 //
 // Author           : Richard C. Bilson
@@ -20,4 +20,5 @@
 #include "Initializer.h"
 #include "Type.h"
+#include "Attribute.h"
 #include "Common/utility.h"
 
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/SynTree/Declaration.h	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -64,5 +64,5 @@
 class DeclarationWithType : public Declaration {
   public:
-	DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage );
+	DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, const std::list< Attribute * > & attributes );
 	DeclarationWithType( const DeclarationWithType &other );
 	virtual ~DeclarationWithType();
@@ -75,4 +75,7 @@
 	int get_scopeLevel() const { return scopeLevel; }
 	void set_scopeLevel( int newValue ) { scopeLevel = newValue; }
+
+	std::list< Attribute * >& get_attributes() { return attributes; }
+	const std::list< Attribute * >& get_attributes() const { return attributes; }
 
 	virtual DeclarationWithType *clone() const = 0;
@@ -87,4 +90,6 @@
 	// shadowed identifiers can be accessed
 	int scopeLevel = 0;
+
+	std::list< Attribute * > attributes;
 };
 
@@ -92,5 +97,5 @@
 	typedef DeclarationWithType Parent;
   public:
-	ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, bool isInline = false, bool isNoreturn = false );
+	ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, const std::list< Attribute * > attributes = std::list< Attribute * >(), bool isInline = false, bool isNoreturn = false );
 	ObjectDecl( const ObjectDecl &other );
 	virtual ~ObjectDecl();
@@ -131,5 +136,4 @@
 	std::list< std::string >& get_oldIdents() { return oldIdents; }
 	std::list< Declaration* >& get_oldDecls() { return oldDecls; }
-	std::list< Attribute * >& get_attributes() { return attributes; }
 
 	virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); }
@@ -143,5 +147,4 @@
 	std::list< std::string > oldIdents;
 	std::list< Declaration* > oldDecls;
-	std::list< Attribute * > attributes;
 };
 
Index: src/SynTree/DeclarationWithType.cc
===================================================================
--- src/SynTree/DeclarationWithType.cc	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/SynTree/DeclarationWithType.cc	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -16,15 +16,18 @@
 #include "Declaration.h"
 #include "Type.h"
+#include "Attribute.h"
 #include "Common/utility.h"
 
-DeclarationWithType::DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage )
-		: Declaration( name, sc, linkage ) {
+DeclarationWithType::DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, const std::list< Attribute * > & attributes )
+		: Declaration( name, sc, linkage ), attributes( attributes ) {
 }
 
 DeclarationWithType::DeclarationWithType( const DeclarationWithType &other )
 		: Declaration( other ), mangleName( other.mangleName ), scopeLevel( other.scopeLevel ) {
+	cloneAll( other.attributes, attributes );
 }
 
 DeclarationWithType::~DeclarationWithType() {
+	deleteAll( attributes );
 }
 
Index: src/SynTree/FunctionDecl.cc
===================================================================
--- src/SynTree/FunctionDecl.cc	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/SynTree/FunctionDecl.cc	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -23,5 +23,5 @@
 
 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 ) {
+		: Parent( name, sc, linkage, attributes ), type( type ), statements( statements ) {
 	set_isInline( isInline );
 	set_isNoreturn( isNoreturn );
@@ -34,5 +34,4 @@
 FunctionDecl::FunctionDecl( const FunctionDecl &other )
 	: Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ) {
-		cloneAll( other.attributes, attributes );
 }
 
@@ -40,5 +39,4 @@
 	delete type;
 	delete statements;
-	deleteAll( attributes );
 }
 
@@ -69,5 +67,5 @@
 	} // if
 
-	printAll( attributes, os, indent );
+	printAll( get_attributes(), os, indent );
 
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
Index: src/SynTree/Label.h
===================================================================
--- src/SynTree/Label.h	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/SynTree/Label.h	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -24,5 +24,5 @@
 class Label {
   public:
-	Label( const std::string & name = "", Statement * labelled = 0 ) : name( name ), labelled( labelled ) {}
+	Label( const std::string & name = "", Statement * labelled = 0, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : name( name ), labelled( labelled ), attributes( attributes ) {}
 	Label( const char * name, Statement * labelled = 0 ) : name( name ), labelled( labelled ) {}
 
Index: src/SynTree/ObjectDecl.cc
===================================================================
--- src/SynTree/ObjectDecl.cc	(revision 73bf8cf2602dc17f80562a5cac0b8c71ae1bcd8a)
+++ src/SynTree/ObjectDecl.cc	(revision f9cebb5b27ac03463e4eca5c0e87d48d548e9502)
@@ -18,9 +18,10 @@
 #include "Initializer.h"
 #include "Expression.h"
+#include "Attribute.h"
 #include "Common/utility.h"
 #include "Statement.h"
 
-ObjectDecl::ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, bool isInline, bool isNoreturn )
-	: Parent( name, sc, linkage ), type( type ), init( init ), bitfieldWidth( bitfieldWidth ) {
+ObjectDecl::ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, const std::list< Attribute * > attributes, bool isInline, bool isNoreturn )
+	: Parent( name, sc, linkage, attributes ), type( type ), init( init ), bitfieldWidth( bitfieldWidth ) {
 	set_isInline( isInline );
 	set_isNoreturn( isNoreturn );
@@ -45,4 +46,6 @@
 		os << LinkageSpec::toString( get_linkage() ) << " ";
 	} // if
+
+	printAll( get_attributes(), os, indent );
 
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
@@ -80,4 +83,6 @@
 	} // if
 
+	// xxx - should printShort print attributes?
+
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
 		os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
