Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 293dc1c9a88a6120c9da7e8d3566ea1feae53953)
+++ src/ResolvExpr/Resolver.cc	(revision 16ba4a6fa0eb60a0cd27fb96882e37dbf94834dd)
@@ -26,7 +26,9 @@
 #include "RenameVars.h"                  // for RenameVars, global_renamer
 #include "Resolver.h"
+#include "ResolveTypeof.h"
 #include "ResolvMode.h"                  // for ResolvMode
 #include "typeops.h"                     // for extractResultType
 #include "Unify.h"                       // for unify
+#include "CompilationState.h"
 #include "AST/Chain.hpp"
 #include "AST/Decl.hpp"
@@ -45,4 +47,5 @@
 #include "SymTab/Autogen.h"              // for SizeType
 #include "SymTab/Indexer.h"              // for Indexer
+#include "SymTab/Mangler.h"              // for Mangler
 #include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
 #include "SynTree/Expression.h"          // for Expression, CastExpr, InitExpr
@@ -1179,15 +1182,19 @@
 	} // anonymous namespace
 
-		ast::ptr< ast::Expr > findSingleExpression(
-			const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
-		) {
-			assert( untyped && type );
-			ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
-			ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
-			removeExtraneousCast( newExpr, symtab );
-			return newExpr;
-		}
+	ast::ptr< ast::Expr > findSingleExpression(
+		const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
+	) {
+		assert( untyped && type );
+		ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
+		ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
+		removeExtraneousCast( newExpr, symtab );
+		return newExpr;
+	}
 
 	namespace {
+		bool structOrUnion( const Candidate & i ) {
+			const ast::Type * t = i.expr->result->stripReferences();
+			return dynamic_cast< const ast::StructInstType * >( t ) || dynamic_cast< const ast::UnionInstType * >( t );
+		}
 		/// Predicate for "Candidate has integral type"
 		bool hasIntegralType( const Candidate & i ) {
@@ -1237,4 +1244,7 @@
 		ast::ptr< ast::Type > functionReturn = nullptr;
 		ast::CurrentObject currentObject;
+		// for work previously in GenInit
+		static InitTweak::ManagedTypes_new managedTypes;
+
 		bool inEnumDecl = false;
 
@@ -1244,7 +1254,9 @@
 		Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
 
-		void previsit( const ast::FunctionDecl * );
+		const ast::FunctionDecl * previsit( const ast::FunctionDecl * );
 		const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
-		void previsit( const ast::ObjectDecl * );
+		const ast::ObjectDecl * previsit( const ast::ObjectDecl * );
+		void previsit( const ast::AggregateDecl * );
+		void previsit( const ast::StructDecl * );
 		void previsit( const ast::EnumDecl * );
 		const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
@@ -1267,10 +1279,18 @@
 		const ast::CatchStmt *       postvisit( const ast::CatchStmt * );
 		const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
+		const ast::WithStmt *        previsit( const ast::WithStmt * );
 
 		const ast::SingleInit *      previsit( const ast::SingleInit * );
 		const ast::ListInit *        previsit( const ast::ListInit * );
 		const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
+
+		void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd);
+
+		void beginScope() { managedTypes.beginScope(); }
+		void endScope() { managedTypes.endScope(); }
 	};
 	// size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver");
+
+	InitTweak::ManagedTypes_new Resolver_new::managedTypes;
 
 	void resolve( ast::TranslationUnit& translationUnit ) {
@@ -1297,7 +1317,107 @@
 	}
 
-	void Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
+	namespace {
+		const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ast::SymbolTable & symtab) {
+			std::string name = attr->normalizedName();
+			if (name == "constructor" || name == "destructor") {
+				if (attr->params.size() == 1) {
+					auto arg = attr->params.front();
+					auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), symtab );
+					auto result = eval(arg);
+
+					auto mutAttr = mutate(attr);
+					mutAttr->params.front() = resolved;
+					if (! result.second) {
+						SemanticWarning(loc, Warning::GccAttributes,
+							toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
+					}
+					else {
+						auto priority = result.first;
+						if (priority < 101) {
+							SemanticWarning(loc, Warning::GccAttributes,
+								toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) );
+						} else if (priority < 201 && ! buildingLibrary()) {
+							SemanticWarning(loc, Warning::GccAttributes,
+								toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) );
+						}
+					}
+					return mutAttr;
+				} else if (attr->params.size() > 1) {
+					SemanticWarning(loc, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) );
+				} else {
+					SemanticWarning(loc, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) );
+				}
+			}
+			return attr;
+		}
+	}
+
+	const ast::FunctionDecl * Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
 		GuardValue( functionReturn );
+
+		assert (functionDecl->unique());
+		if (!functionDecl->has_body() && !functionDecl->withExprs.empty()) {
+			SemanticError(functionDecl->location, functionDecl, "Function without body has with declarations");
+		}
+
+		if (!functionDecl->isTypeFixed) {
+			auto mutDecl = mutate(functionDecl);
+			auto mutType = mutDecl->type.get_and_mutate();
+
+			for (auto & attr: mutDecl->attributes) {
+				attr = handleAttribute(mutDecl->location, attr, symtab);
+			}
+
+			// handle assertions. (seems deep)
+
+			symtab.enterScope();
+			for (auto & typeParam : mutType->forall) {
+				auto mutParam = typeParam.get_and_mutate();
+				symtab.addType(mutParam);
+				for (auto & asst : mutParam->assertions) {
+					asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab);
+					symtab.addId(asst);
+				}
+				typeParam = mutParam;
+			}
+
+			// temporarily adds params to symbol table.
+			// actual scoping rules for params and withexprs differ - see Pass::visit(FunctionDecl)
+
+			std::vector<ast::ptr<ast::Type>> paramTypes;
+			std::vector<ast::ptr<ast::Type>> returnTypes;
+
+			for (auto & param : mutDecl->params) {
+				param = fixObjectType(param.strict_as<ast::ObjectDecl>(), symtab);
+				symtab.addId(param);
+				paramTypes.emplace_back(param->get_type());
+			}
+			for (auto & ret : mutDecl->returns) {
+				ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), symtab);
+				returnTypes.emplace_back(ret->get_type());
+			}
+			// since function type in decl is just a view of param types, need to update that as well
+			mutType->params = std::move(paramTypes);
+			mutType->returns = std::move(returnTypes);
+
+			std::list<ast::ptr<ast::Stmt>> newStmts;
+			resolveWithExprs (mutDecl->withExprs, newStmts);
+
+			if (mutDecl->stmts) {
+				auto mutStmt = mutDecl->stmts.get_and_mutate();
+				mutStmt->kids.splice(mutStmt->kids.begin(), std::move(newStmts));
+				mutDecl->stmts = mutStmt;
+			}
+
+			symtab.leaveScope();
+
+			mutDecl->mangleName = Mangle::mangle(mutDecl);
+			mutDecl->isTypeFixed = true;
+			functionDecl = mutDecl;
+		}
+		managedTypes.handleDWT(functionDecl);
+
 		functionReturn = extractResultType( functionDecl->type );
+		return functionDecl;
 	}
 
@@ -1330,5 +1450,5 @@
 	}
 
-	void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
+	const ast::ObjectDecl * Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
 		// To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
 		// class-variable `initContext` is changed multiple times because the LHS is analyzed
@@ -1338,11 +1458,53 @@
 		// selecting the RHS.
 		GuardValue( currentObject );
-		currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
+
 		if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
 			// enumerator initializers should not use the enum type to initialize, since the
 			// enum type is still incomplete at this point. Use `int` instead.
+			objectDecl = fixObjectType(objectDecl, symtab);
 			currentObject = ast::CurrentObject{
 				objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
 		}
+		else {
+			if (!objectDecl->isTypeFixed) {
+				auto newDecl = fixObjectType(objectDecl, symtab);
+				auto mutDecl = mutate(newDecl);
+				
+				// generate CtorInit wrapper when necessary.
+				// in certain cases, fixObjectType is called before reaching
+				// this object in visitor pass, thus disabling CtorInit codegen.
+				// this happens on aggregate members and function parameters.
+				if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) {
+					// constructed objects cannot be designated
+					if ( InitTweak::isDesignated( mutDecl->init ) ) SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
+					// constructed objects should not have initializers nested too deeply
+					if ( ! InitTweak::checkInitDepth( mutDecl ) ) SemanticError( mutDecl, "Managed object's initializer is too deep " );
+
+					mutDecl->init = InitTweak::genCtorInit( mutDecl->location, mutDecl );
+				}
+
+				objectDecl = mutDecl;
+			}
+			currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
+		}
+		
+		return objectDecl;
+	}
+
+	void Resolver_new::previsit( const ast::AggregateDecl * _aggDecl ) {
+		auto aggDecl = mutate(_aggDecl);
+		assertf(aggDecl == _aggDecl, "type declarations must be unique");
+
+		for (auto & member: aggDecl->members) {
+			// nested type decls are hoisted already. no need to do anything
+			if (auto obj = member.as<ast::ObjectDecl>()) {
+				member = fixObjectType(obj, symtab);
+			}
+		}
+	}
+
+	void Resolver_new::previsit( const ast::StructDecl * structDecl ) {
+		previsit(static_cast<const ast::AggregateDecl *>(structDecl));
+		managedTypes.handleStruct(structDecl);
 	}
 
@@ -1351,5 +1513,7 @@
 		GuardValue( inEnumDecl );
 		inEnumDecl = true;
-	}
+		// don't need to fix types for enum fields
+	}
+
 
 	const ast::StaticAssertDecl * Resolver_new::previsit(
@@ -1780,4 +1944,31 @@
 	}
 
+	const ast::WithStmt * Resolver_new::previsit( const ast::WithStmt * withStmt ) {
+		auto mutStmt = mutate(withStmt);
+		resolveWithExprs(mutStmt->exprs, stmtsToAddBefore);
+		return mutStmt;
+	}
+
+	void Resolver_new::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) {
+		for (auto & expr : exprs) {
+			// only struct- and union-typed expressions are viable candidates
+			expr = findKindExpression( expr, symtab, structOrUnion, "with expression" );
+
+			// if with expression might be impure, create a temporary so that it is evaluated once
+			if ( Tuples::maybeImpure( expr ) ) {
+				static UniqueName tmpNamer( "_with_tmp_" );
+				const CodeLocation loc = expr->location;
+				auto tmp = new ast::ObjectDecl(loc, tmpNamer.newName(), expr->result, new ast::SingleInit(loc, expr ) );
+				expr = new ast::VariableExpr( loc, tmp );
+				stmtsToAdd.push_back( new ast::DeclStmt(loc, tmp ) );
+				if ( InitTweak::isConstructable( tmp->type ) ) {
+					// generate ctor/dtor and resolve them
+					tmp->init = InitTweak::genCtorInit( loc, tmp );
+				}
+				// since tmp is freshly created, this should modify tmp in-place
+				tmp->accept( *visitor );
+			}
+		}
+	}
 
 
