Index: src/GenPoly/Box.cpp
===================================================================
--- src/GenPoly/Box.cpp	(revision 4eb3a7c5d08b7aedeb694f5b4b465e652dd55d5e)
+++ src/GenPoly/Box.cpp	(revision 46aa60e0a6177a3ae6c22a341d26008220f06b1f)
@@ -1109,9 +1109,6 @@
 	);
 
-	for ( auto group : group_iterate( realType->assertions,
-			adapterType->assertions, adaptee->assertions ) ) {
-		auto assertArg = std::get<0>( group );
-		auto assertParam = std::get<1>( group );
-		auto assertReal = std::get<2>( group );
+	for ( auto const & [assertArg, assertParam, assertReal] : group_iterate(
+			realType->assertions, adapterType->assertions, adaptee->assertions ) ) {
 		adapteeApp->args.push_back( makeAdapterArg(
 			assertParam->var, assertArg->var->get_type(),
@@ -1970,7 +1967,6 @@
 	bool hasDynamicLayout = false;
 
-	for ( auto pair : group_iterate( baseParams, typeParams ) ) {
-		auto baseParam = std::get<0>( pair );
-		auto typeParam = std::get<1>( pair );
+	for ( auto const & [baseParam, typeParam] : group_iterate(
+			baseParams, typeParams ) ) {
 		if ( !baseParam->isComplete() ) continue;
 		ast::TypeExpr const * typeExpr = typeParam.as<ast::TypeExpr>();
Index: src/InitTweak/FixInit.cpp
===================================================================
--- src/InitTweak/FixInit.cpp	(revision 4eb3a7c5d08b7aedeb694f5b4b465e652dd55d5e)
+++ src/InitTweak/FixInit.cpp	(revision 46aa60e0a6177a3ae6c22a341d26008220f06b1f)
@@ -1134,5 +1134,5 @@
 			ast::Expr * thisExpr = new ast::CastExpr(funcDecl->location, new ast::VariableExpr(funcDecl->location, thisParam ), thisParam->get_type()->stripReferences());
 			ast::Expr * memberDest = new ast::MemberExpr(funcDecl->location, field, thisExpr );
-			ast::ptr<ast::Stmt> callStmt = SymTab::genImplicitCall( srcParam, memberDest, loc, function->name, field, static_cast<SymTab::LoopDirection>(isCtor) );
+			const ast::Stmt * callStmt = SymTab::genImplicitCall( srcParam, memberDest, loc, function->name, field, static_cast<SymTab::LoopDirection>(isCtor) );
 
 			if ( callStmt ) {
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 4eb3a7c5d08b7aedeb694f5b4b465e652dd55d5e)
+++ src/InitTweak/GenInit.cc	(revision 46aa60e0a6177a3ae6c22a341d26008220f06b1f)
@@ -239,5 +239,5 @@
 					if ( varExpr->var == retVal ) return stmt;
 				}
-				ast::ptr<ast::Stmt> ctorStmt = genCtorDtor(
+				const ast::Stmt * ctorStmt = genCtorDtor(
 					retVal->location, "?{}", retVal, stmt->expr );
 				assertf( ctorStmt,
@@ -327,5 +327,5 @@
 void ManagedTypes::endScope() { managedTypes.endScope(); }
 
-ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) {
+const ast::Stmt * genCtorDtor( const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg ) {
 	assertf(objDecl, "genCtorDtor passed null objDecl");
 	InitExpander srcParam(arg);
Index: src/InitTweak/GenInit.h
===================================================================
--- src/InitTweak/GenInit.h	(revision 4eb3a7c5d08b7aedeb694f5b4b465e652dd55d5e)
+++ src/InitTweak/GenInit.h	(revision 46aa60e0a6177a3ae6c22a341d26008220f06b1f)
@@ -33,5 +33,5 @@
 
 /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
-ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr);
+const ast::Stmt * genCtorDtor( const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr );
 
 /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 4eb3a7c5d08b7aedeb694f5b4b465e652dd55d5e)
+++ src/Parser/parser.yy	(revision 46aa60e0a6177a3ae6c22a341d26008220f06b1f)
@@ -1081,7 +1081,6 @@
 	| logical_OR_expression '?' comma_expression ':' conditional_expression
 		{ $$ = new ExpressionNode( build_cond( yylloc, $1, $3, $5 ) ); }
-		// FIX ME: computes $1 twice
 	| logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand
-		{ $$ = new ExpressionNode( build_cond( yylloc, $1, $1->clone(), $4 ) ); }
+		{ $$ = new ExpressionNode( build_cond( yylloc, $1, nullptr, $4 ) ); }
 	;
 
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision 4eb3a7c5d08b7aedeb694f5b4b465e652dd55d5e)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision 46aa60e0a6177a3ae6c22a341d26008220f06b1f)
@@ -1512,13 +1512,16 @@
 	void Finder::postvisit( const ast::ConditionalExpr * conditionalExpr ) {
 		// candidates for condition
+		ast::ptr<ast::Expr> arg1 = notZeroExpr( conditionalExpr->arg1 );
 		CandidateFinder finder1( context, tenv );
-		ast::ptr<ast::Expr> arg1 = notZeroExpr( conditionalExpr->arg1 );
 		finder1.find( arg1, ResolveMode::withAdjustment() );
 		if ( finder1.candidates.empty() ) return;
 
 		// candidates for true result
+		// FIX ME: resolves and runs arg1 twice when arg2 is missing.
+		ast::Expr const * arg2 = conditionalExpr->arg2;
+		arg2 = arg2 ? arg2 : conditionalExpr->arg1.get();
 		CandidateFinder finder2( context, tenv );
 		finder2.allowVoid = true;
-		finder2.find( conditionalExpr->arg2, ResolveMode::withAdjustment() );
+		finder2.find( arg2, ResolveMode::withAdjustment() );
 		if ( finder2.candidates.empty() ) return;
 
Index: src/SymTab/GenImplicitCall.cpp
===================================================================
--- src/SymTab/GenImplicitCall.cpp	(revision 4eb3a7c5d08b7aedeb694f5b4b465e652dd55d5e)
+++ src/SymTab/GenImplicitCall.cpp	(revision 46aa60e0a6177a3ae6c22a341d26008220f06b1f)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// GenImplicitCall.hpp --
+// GenImplicitCall.cpp -- Generate code for implicit operator calls.
 //
 // Author           : Andrew Beach
@@ -31,8 +31,9 @@
 namespace {
 
-template< typename OutIter >
+using Inserter = std::back_insert_iterator<std::list<ast::ptr<ast::Stmt>>>;
+
 ast::ptr< ast::Stmt > genCall(
 	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
-	const CodeLocation & loc, const std::string & fname, OutIter && out,
+	const CodeLocation & loc, const std::string & fname, Inserter && out,
 	const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
 
@@ -41,8 +42,7 @@
 /// optionally returns a statement which must be inserted prior to the containing loop, if
 /// there is one
-template< typename OutIter >
 ast::ptr< ast::Stmt > genScalarCall(
 	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
-	const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
+	const CodeLocation & loc, std::string fname, Inserter && out, const ast::Type * type,
 	const ast::Type * addCast = nullptr
 ) {
@@ -97,8 +97,7 @@
 /// Store in out a loop which calls fname on each element of the array with srcParam and
 /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
-template< typename OutIter >
 void genArrayCall(
 	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
-	const CodeLocation & loc, const std::string & fname, OutIter && out,
+	const CodeLocation & loc, const std::string & fname, Inserter && out,
 	const ast::ArrayType * array, const ast::Type * addCast = nullptr,
 	LoopDirection forward = LoopForward
@@ -166,18 +165,17 @@
 }
 
-template< typename OutIter >
 ast::ptr< ast::Stmt > genCall(
 	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
-	const CodeLocation & loc, const std::string & fname, OutIter && out,
+	const CodeLocation & loc, const std::string & fname, Inserter && out,
 	const ast::Type * type, const ast::Type * addCast, LoopDirection forward
 ) {
 	if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
 		genArrayCall(
-			srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,
+			srcParam, dstParam, loc, fname, std::forward< Inserter&& >( out ), at, addCast,
 			forward );
 		return {};
 	} else {
 		return genScalarCall(
-			srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );
+			srcParam, dstParam, loc, fname, std::forward< Inserter&& >( out ), type, addCast );
 	}
 }
@@ -185,5 +183,5 @@
 } // namespace
 
-ast::ptr< ast::Stmt > genImplicitCall(
+const ast::Stmt * genImplicitCall(
 	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
 	const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
@@ -191,5 +189,5 @@
 ) {
 	// unnamed bit fields are not copied as they cannot be accessed
-	if ( isUnnamedBitfield( obj ) ) return {};
+	if ( isUnnamedBitfield( obj ) ) return nullptr;
 
 	ast::ptr< ast::Type > addCast;
@@ -199,22 +197,18 @@
 	}
 
-	std::vector< ast::ptr< ast::Stmt > > stmts;
+	std::list< ast::ptr< ast::Stmt > > stmts;
 	genCall(
 		srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
 
-	if ( stmts.empty() ) {
-		return {};
-	} else if ( stmts.size() == 1 ) {
-		const ast::Stmt * callStmt = stmts.front();
-		if ( addCast ) {
-			// implicitly generated ctor/dtor calls should be wrapped so that later passes are
-			// aware they were generated.
-			callStmt = new ast::ImplicitCtorDtorStmt( callStmt->location, callStmt );
-		}
-		return callStmt;
-	} else {
-		assert( false );
-		return {};
-	}
+	if ( stmts.empty() ) return nullptr;
+	assert( stmts.size() == 1 );
+
+	const ast::Stmt * callStmt = stmts.front().release();
+	// Implicitly generated ctor/dtor calls should be wrapped so that
+	// later passes are aware they were generated.
+	if ( addCast ) {
+		callStmt = new ast::ImplicitCtorDtorStmt( callStmt->location, callStmt );
+	}
+	return callStmt;
 }
 
@@ -226,4 +220,2 @@
 // compile-command: "make install" //
 // End: //
-
-
Index: src/SymTab/GenImplicitCall.hpp
===================================================================
--- src/SymTab/GenImplicitCall.hpp	(revision 4eb3a7c5d08b7aedeb694f5b4b465e652dd55d5e)
+++ src/SymTab/GenImplicitCall.hpp	(revision 46aa60e0a6177a3ae6c22a341d26008220f06b1f)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// GenImplicitCall.hpp --
+// GenImplicitCall.hpp -- Generate code for implicit operator calls.
 //
 // Author           : Andrew Beach
@@ -25,5 +25,5 @@
 /// Returns a generated call expression to function fname with srcParam and
 /// dstParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
-ast::ptr<ast::Stmt> genImplicitCall(
+const ast::Stmt * genImplicitCall(
 	InitTweak::InitExpander & srcParam, const ast::Expr * dstParam,
 	const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
Index: src/Validate/Autogen.cpp
===================================================================
--- src/Validate/Autogen.cpp	(revision 4eb3a7c5d08b7aedeb694f5b4b465e652dd55d5e)
+++ src/Validate/Autogen.cpp	(revision 46aa60e0a6177a3ae6c22a341d26008220f06b1f)
@@ -133,6 +133,5 @@
 	/// Generates a single struct member operation.
 	/// (constructor call, destructor call, assignment call)
-	// This is managed because it uses another helper that returns a ast::ptr.
-	ast::ptr<ast::Stmt> makeMemberOp(
+	const ast::Stmt * makeMemberOp(
 		const CodeLocation& location,
 		const ast::ObjectDecl * dstParam, const ast::Expr * src,
@@ -524,5 +523,5 @@
 }
 
-ast::ptr<ast::Stmt> StructFuncGenerator::makeMemberOp(
+const ast::Stmt * StructFuncGenerator::makeMemberOp(
 		const CodeLocation& location, const ast::ObjectDecl * dstParam,
 		const ast::Expr * src, const ast::ObjectDecl * field,
@@ -539,5 +538,5 @@
 		)
 	);
-	auto stmt = genImplicitCall(
+	const ast::Stmt * stmt = genImplicitCall(
 		srcParam, dstSelect, location, func->name,
 		field, direction
@@ -597,9 +596,9 @@
 			location, field, new ast::VariableExpr( location, srcParam )
 		) : nullptr;
-		ast::ptr<ast::Stmt> stmt =
+		const ast::Stmt * stmt =
 			makeMemberOp( location, dstParam, srcSelect, field, func, direction );
 
 		if ( nullptr != stmt ) {
-			stmts->kids.push_back( stmt );
+			stmts->kids.emplace_back( stmt );
 		}
 	}
@@ -622,5 +621,5 @@
 	for ( auto param = params.begin() + 1 ; current != end ; ++current ) {
 		const ast::ptr<ast::Decl> & member = *current;
-		ast::ptr<ast::Stmt> stmt = nullptr;
+		const ast::Stmt * stmt = nullptr;
 		auto field = member.as<ast::ObjectDecl>();
 		// Not sure why it could be null.
@@ -640,5 +639,5 @@
 
 		if ( nullptr != stmt ) {
-			stmts->kids.push_back( stmt );
+			stmts->kids.emplace_back( stmt );
 		}
 	}
