Index: src/SynTree/Attribute.cc
===================================================================
--- src/SynTree/Attribute.cc	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
+++ src/SynTree/Attribute.cc	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -0,0 +1,47 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Attribute.cc --
+//
+// Author           : Rob Schluntz
+// Created On       : Mon June 06 14:51:16 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Mon June 06 14:54:48 2016
+// Update Count     : 1
+//
+
+#include <cassert>
+
+#include "Common/utility.h"
+#include "Attribute.h"
+#include "Expression.h"
+
+Attribute::Attribute( const Attribute &other ) : name( other.name ) {
+  cloneAll( other.parameters, parameters );
+}
+
+Attribute::~Attribute() {
+  deleteAll( parameters );
+}
+
+void Attribute::print( std::ostream &os, int indent ) const {
+  using std::endl;
+  using std::string;
+
+  if ( ! empty() ) {
+    os << "Attribute with name: " << name;
+    if ( ! parameters.empty() ) {
+      os << " with parameters: " << endl;
+      printAll( parameters, os, indent );
+    }
+  }
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SynTree/Attribute.h
===================================================================
--- src/SynTree/Attribute.h	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
+++ src/SynTree/Attribute.h	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -0,0 +1,43 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Declaration.h --
+//
+// Author           : Richard C. Bilson
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 06 16:26:12 2016
+// Update Count     : 33
+//
+
+#ifndef GCC_ATTRIBUTE_H
+#define GCC_ATTRIBUTE_H
+
+#include "SynTree.h"
+
+// GCC attribute
+// https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Attribute-Syntax.html#Attribute-Syntax
+class Attribute {
+  public:
+  Attribute( std::string name = "", const std::list< Expression * > & parameters = std::list< Expression * >() ) : name( name ), parameters( parameters ) {}
+  Attribute( const Attribute &other );
+  virtual ~Attribute();
+
+  std::string get_name() const { return name; }
+  void set_name( const std::string & newValue ) { name = newValue; }
+  std::list< Expression * > & get_parameters() { return parameters; }
+  bool empty() const { return name == ""; }
+
+  Attribute * clone() const { return new Attribute( *this ); }
+  void print( std:: ostream &os, int indent = 0 ) const;
+
+  private:
+  std::string name;
+  // to keep things nice and tight, use NameExpr for special identifier parameters
+  std::list< Expression * > parameters;
+};
+
+#endif
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Declaration.h	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -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 e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/FunctionDecl.cc	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -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/Initializer.cc
===================================================================
--- src/SynTree/Initializer.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Initializer.cc	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -20,4 +20,7 @@
 
 Initializer::Initializer( bool maybeConstructed ) : maybeConstructed( maybeConstructed ) {}
+Initializer::Initializer( const Initializer & other ) : maybeConstructed( other.maybeConstructed ) {
+}
+
 
 Initializer::~Initializer() {}
@@ -39,7 +42,7 @@
 }
 
-SingleInit::~SingleInit() {}
-
-SingleInit *SingleInit::clone() const { return new SingleInit( *this); }
+SingleInit::~SingleInit() {
+	deleteAll(designators);
+}
 
 void SingleInit::print( std::ostream &os, int indent ) {
@@ -58,11 +61,10 @@
 
 ListInit::ListInit( const std::list<Initializer*> &_initializers, const std::list<Expression *> &_designators, bool maybeConstructed )
-	: Initializer( maybeConstructed), initializers( _initializers ), designators( _designators ) {
+	: Initializer( maybeConstructed ), initializers( _initializers ), designators( _designators ) {
 }
 
-ListInit::~ListInit() {}
-
-ListInit *ListInit::clone() const {
-	return new ListInit( *this );
+ListInit::~ListInit() {
+	deleteAll( initializers );
+	deleteAll( designators );
 }
 
@@ -85,11 +87,11 @@
 
 ConstructorInit::ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init ) : Initializer( true ), ctor( ctor ), dtor( dtor ), init( init ) {}
+ConstructorInit::ConstructorInit( const ConstructorInit &other ) : Initializer( other ), ctor( maybeClone( other.ctor ) ), dtor( maybeClone( other.dtor ) ), init( maybeClone( other.init ) ) {
+}
+
 ConstructorInit::~ConstructorInit() {
 	delete ctor;
+	delete dtor;
 	delete init;
-}
-
-ConstructorInit *ConstructorInit::clone() const {
-	return new ConstructorInit( *this );
 }
 
Index: src/SynTree/Initializer.h
===================================================================
--- src/SynTree/Initializer.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Initializer.h	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -20,4 +20,5 @@
 #include "Visitor.h"
 #include "Mutator.h"
+#include "Type.h"
 
 #include <cassert>
@@ -28,4 +29,5 @@
 	//	Initializer( std::string _name = std::string(""), int _pos = 0 );
 	Initializer( bool maybeConstructed );
+	Initializer( const Initializer & other );
 	virtual ~Initializer();
 
@@ -68,5 +70,5 @@
 	std::list<Expression *> &get_designators() { return designators; }
 
-	virtual SingleInit *clone() const;
+	virtual SingleInit *clone() const { return new SingleInit( *this); }
 	virtual void accept( Visitor &v ) { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
@@ -94,5 +96,5 @@
 	std::list<Initializer*>::iterator end_initializers() { return initializers.end(); }
 
-	virtual ListInit *clone() const;
+	virtual ListInit *clone() const { return new ListInit( *this ); }
 	virtual void accept( Visitor &v ) { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
@@ -108,4 +110,5 @@
   public:
 	ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init );
+	ConstructorInit( const ConstructorInit &other );
 	virtual ~ConstructorInit();
 
@@ -117,5 +120,5 @@
 	Initializer * get_init() const { return init; }
 
-	virtual ConstructorInit *clone() const;
+	ConstructorInit *clone() const { return new ConstructorInit( *this ); }
 	virtual void accept( Visitor &v ) { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
Index: src/SynTree/Mutator.cc
===================================================================
--- src/SynTree/Mutator.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Mutator.cc	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -182,4 +182,9 @@
 }
 
+Statement *Mutator::mutate( ImplicitCtorDtorStmt *impCtorDtorStmt ) {
+	impCtorDtorStmt->set_callStmt( maybeMutate( impCtorDtorStmt->get_callStmt(), *this ) );
+	return impCtorDtorStmt;
+}
+
 Expression *Mutator::mutate( ApplicationExpr *applicationExpr ) {
 	mutateAll( applicationExpr->get_results(), *this );
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Mutator.h	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -52,4 +52,5 @@
 	virtual NullStmt* mutate( NullStmt *nullStmt );
 	virtual Statement* mutate( DeclStmt *declStmt );
+	virtual Statement* mutate( ImplicitCtorDtorStmt *impCtorDtorStmt );
 
 	virtual Expression* mutate( ApplicationExpr *applicationExpr );
Index: src/SynTree/Statement.cc
===================================================================
--- src/SynTree/Statement.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Statement.cc	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -358,5 +358,5 @@
 
 void CatchStmt::print( std::ostream &os, int indent ) const {
-	os << string( indent, ' ' ) << "Catch Statement" << endl;
+	os << "Catch Statement" << endl;
 
 	os << string( indent, ' ' ) << "... catching" << endl;
@@ -383,5 +383,5 @@
 
 void FinallyStmt::print( std::ostream &os, int indent ) const {
-	os << string( indent, ' ' ) << "Finally Statement" << endl;
+	os << "Finally Statement" << endl;
 	os << string( indent + 2, ' ' ) << "with block: " << endl;
 	block->print( os, indent + 4 );
@@ -393,4 +393,21 @@
 void NullStmt::print( std::ostream &os, int indent ) const {
 	os << "Null Statement" << endl ;
+}
+
+ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( Statement * callStmt ) : Statement( std::list<Label>() ), callStmt( callStmt ) {
+	assert( callStmt );
+}
+
+ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( const ImplicitCtorDtorStmt & other ) : Statement( other ), callStmt( other.callStmt ) {
+}
+
+ImplicitCtorDtorStmt::~ImplicitCtorDtorStmt() {
+}
+
+void ImplicitCtorDtorStmt::print( std::ostream &os, int indent ) const {
+	os << "Implicit Ctor Dtor Statement" << endl;
+	os << string( indent + 2, ' ' ) << "with Ctor/Dtor: ";
+	callStmt->print( os, indent + 2);
+	os << endl;
 }
 
Index: src/SynTree/Statement.h
===================================================================
--- src/SynTree/Statement.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Statement.h	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -21,4 +21,5 @@
 #include "Mutator.h"
 #include "Common/SemanticError.h"
+#include "Type.h"
 
 class Statement {
@@ -394,5 +395,5 @@
 	virtual ~DeclStmt();
 
-	Declaration *get_decl() { return decl; }
+	Declaration *get_decl() const { return decl; }
 	void set_decl( Declaration *newValue ) { decl = newValue; }
 
@@ -404,4 +405,28 @@
 	Declaration *decl;
 };
+
+
+/// represents an implicit application of a constructor or destructor. Qualifiers are replaced
+/// immediately before and after the call so that qualified objects can be constructed
+/// with the same functions as unqualified objects.
+class ImplicitCtorDtorStmt : public Statement {
+  public:
+	ImplicitCtorDtorStmt( Statement * callStmt );
+	ImplicitCtorDtorStmt( const ImplicitCtorDtorStmt & other );
+	virtual ~ImplicitCtorDtorStmt();
+
+	Statement *get_callStmt() const { return callStmt; }
+	void set_callStmt( Statement * newValue ) { callStmt = newValue; }
+
+	virtual ImplicitCtorDtorStmt *clone() const { return new ImplicitCtorDtorStmt( *this ); }
+	virtual void accept( Visitor &v ) { v.visit( this ); }
+	virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }
+	virtual void print( std::ostream &os, int indent = 0 ) const;
+
+  private:
+	// Non-owned pointer to the constructor/destructor statement
+	Statement * callStmt;
+};
+
 
 std::ostream & operator<<( std::ostream & out, Statement * statement );
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/SynTree.h	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -56,4 +56,5 @@
 class DeclStmt;
 class NullStmt;
+class ImplicitCtorDtorStmt;
 
 class Expression;
@@ -117,4 +118,7 @@
 class TypeSubstitution;
 
+// gcc attribute
+class Attribute;
+
 #endif // SYNTREE_H
 
Index: src/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Type.cc	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Type.cc -- 
+// Type.cc --
 //
 // Author           : Richard C. Bilson
@@ -54,4 +54,25 @@
 }
 
+void Type::Qualifiers::print( std::ostream &os, int indent ) const {
+	if ( isConst ) {
+		os << "const ";
+	} // if
+	if ( isVolatile ) {
+		os << "volatile ";
+	} // if
+	if ( isRestrict ) {
+		os << "restrict ";
+	} // if
+	if ( isLvalue ) {
+		os << "lvalue ";
+	} // if
+	if ( isAtomic ) {
+		os << "_Atomic ";
+	} // if
+	if ( isAttribute ) {
+		os << "__attribute(( )) ";
+	} // if
+}
+
 void Type::print( std::ostream &os, int indent ) const {
 	if ( ! forall.empty() ) {
@@ -60,22 +81,5 @@
 		os << std::string( indent+2, ' ' );
 	} // if
-	if ( tq.isConst ) {
-		os << "const ";
-	} // if
-	if ( tq.isVolatile ) {
-		os << "volatile ";
-	} // if
-	if ( tq.isRestrict ) {
-		os << "restrict ";
-	} // if
-	if ( tq.isLvalue ) {
-		os << "lvalue ";
-	} // if
-	if ( tq.isAtomic ) {
-		os << "_Atomic ";
-	} // if
-	if ( tq.isAttribute ) {
-		os << "__attribute(( )) ";
-	} // if
+	tq.print( os, indent );
 }
 
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Type.h	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -36,4 +36,5 @@
 		bool operator<( const Qualifiers &other );
 		bool operator>( const Qualifiers &other );
+		void print( std::ostream &os, int indent = 0 ) const;
 
 		bool isConst;
Index: src/SynTree/Visitor.cc
===================================================================
--- src/SynTree/Visitor.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Visitor.cc	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -152,4 +152,8 @@
 }
 
+void Visitor::visit( ImplicitCtorDtorStmt *impCtorDtorStmt ) {
+	maybeAccept( impCtorDtorStmt->get_callStmt(), *this );
+}
+
 void Visitor::visit( ApplicationExpr *applicationExpr ) {
 	acceptAll( applicationExpr->get_results(), *this );
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Visitor.h	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -52,4 +52,5 @@
 	virtual void visit( NullStmt *nullStmt );
 	virtual void visit( DeclStmt *declStmt );
+	virtual void visit( ImplicitCtorDtorStmt *impCtorDtorStmt );
 
 	virtual void visit( ApplicationExpr *applicationExpr );
Index: src/SynTree/module.mk
===================================================================
--- src/SynTree/module.mk	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/module.mk	(revision e50db109d71f2d05534388d73f26a49091a8ff14)
@@ -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
 
