Index: src/CodeGen/OperatorTable.cc
===================================================================
--- src/CodeGen/OperatorTable.cc	(revision 53a8e68bb29ee1058f8e4557c98ee2f853273859)
+++ src/CodeGen/OperatorTable.cc	(revision bff227f73387fd7ed67a8a31545259b27d4ddc24)
@@ -14,6 +14,7 @@
 //
 
-#include <map>      // for map, _Rb_tree_const_iterator, map<>::const_iterator
-#include <utility>  // for pair
+#include <algorithm>  // for any_of
+#include <map>        // for map, _Rb_tree_const_iterator, map<>::const_iterator
+#include <utility>    // for pair
 
 #include "OperatorTable.h"
@@ -91,4 +92,39 @@
 		} // if
 	}
+
+	/// determines if a given function name is one of the operator types between [begin, end)
+	template<typename Iterator>
+	bool isOperatorType( const std::string & funcName, Iterator begin, Iterator end ) {
+		OperatorInfo info;
+		if ( operatorLookup( funcName, info ) ) {
+			return std::find( begin, end, info.type ) != end;
+		}
+		return false;
+	}
+
+	bool isConstructor( const std::string & funcName ) {
+		static OperatorType types[] = { OT_CTOR };
+		return isOperatorType( funcName, std::begin(types), std::end(types) );
+	}
+
+	bool isDestructor( const std::string & funcName ) {
+		static OperatorType types[] = { OT_DTOR };
+		return isOperatorType( funcName, std::begin(types), std::end(types) );
+	}
+
+	bool isAssignment( const std::string & funcName ) {
+		static OperatorType types[] = { OT_PREFIXASSIGN, OT_POSTFIXASSIGN, OT_INFIXASSIGN };
+		return isOperatorType( funcName, std::begin(types), std::end(types) );
+	}
+
+	bool isCtorDtor( const std::string & funcName ) {
+		static OperatorType types[] = { OT_CTOR, OT_DTOR };
+		return isOperatorType( funcName, std::begin(types), std::end(types) );
+	}
+
+	bool isCtorDtorAssign( const std::string & funcName ) {
+		static OperatorType types[] = { OT_CTOR, OT_DTOR, OT_PREFIXASSIGN, OT_POSTFIXASSIGN, OT_INFIXASSIGN };
+		return isOperatorType( funcName, std::begin(types), std::end(types) );
+	}
 } // namespace CodeGen
 
Index: src/CodeGen/OperatorTable.h
===================================================================
--- src/CodeGen/OperatorTable.h	(revision 53a8e68bb29ee1058f8e4557c98ee2f853273859)
+++ src/CodeGen/OperatorTable.h	(revision bff227f73387fd7ed67a8a31545259b27d4ddc24)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// OperatorTable.h -- 
+// OperatorTable.h --
 //
 // Author           : Richard C. Bilson
@@ -43,4 +43,10 @@
 
 	bool operatorLookup( std::string funcName, OperatorInfo &info );
+
+	bool isConstructor( const std::string & );
+	bool isDestructor( const std::string & );
+	bool isAssignment( const std::string & );
+	bool isCtorDtor( const std::string & );
+	bool isCtorDtorAssign( const std::string & );
 } // namespace CodeGen
 
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision 53a8e68bb29ee1058f8e4557c98ee2f853273859)
+++ src/Concurrency/Keywords.cc	(revision bff227f73387fd7ed67a8a31545259b27d4ddc24)
@@ -22,5 +22,6 @@
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/utility.h"        // for deleteAll, map_range
-#include "InitTweak/InitTweak.h"   // for isConstructor
+#include "CodeGen/OperatorTable.h" // for isConstructor
+#include "InitTweak/InitTweak.h"   // for getPointerBase
 #include "Parser/LinkageSpec.h"    // for Cforall
 #include "SymTab/AddVisit.h"       // for acceptAndAdd
@@ -522,5 +523,5 @@
 		Visitor::visit(decl);
 
-		if( ! InitTweak::isConstructor(decl->get_name()) ) return;
+		if( ! CodeGen::isConstructor(decl->get_name()) ) return;
 
 		DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 53a8e68bb29ee1058f8e4557c98ee2f853273859)
+++ src/GenPoly/Box.cc	(revision bff227f73387fd7ed67a8a31545259b27d4ddc24)
@@ -55,4 +55,6 @@
 #include "Common/UniqueName.h"
 #include "Common/utility.h"
+
+#include "CodeGen/OperatorTable.h"
 
 #include "InitTweak/InitTweak.h"
@@ -567,5 +569,5 @@
 			// To compound the issue, the right side can be *x, etc. because of lvalue-returning functions
 			if ( UntypedExpr * assign = dynamic_cast< UntypedExpr * >( commaExpr->get_arg1() ) ) {
-				if ( InitTweak::isAssignment( InitTweak::getFunctionName( assign ) ) ) {
+				if ( CodeGen::isAssignment( InitTweak::getFunctionName( assign ) ) ) {
 					assert( assign->get_args().size() == 2 );
 					if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( assign->get_args().back() ) ) {
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 53a8e68bb29ee1058f8e4557c98ee2f853273859)
+++ src/InitTweak/FixInit.cc	(revision bff227f73387fd7ed67a8a31545259b27d4ddc24)
@@ -26,4 +26,5 @@
 #include "FixGlobalInit.h"
 #include "CodeGen/GenType.h"  // for warning/error messages
+#include "CodeGen/OperatorTable.h"
 #include "Common/PassVisitor.h"
 #include "GenPoly/DeclMutator.h"
@@ -363,5 +364,5 @@
 					FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
 					assert( ftype );
-					if ( isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
+					if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
 						Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
 						Type * t2 = ftype->get_parameters().back()->get_type();
@@ -372,5 +373,5 @@
 							return appExpr;
 						} // if
-					} else if ( isDestructor( funcDecl->get_name() ) ) {
+					} else if ( CodeGen::isDestructor( funcDecl->get_name() ) ) {
 						// correctness: never copy construct arguments to a destructor
 						return appExpr;
@@ -975,5 +976,5 @@
 			if ( ! funcDecl ) return false;
 			if ( ! funcDecl->get_statements() ) return false;
-			return isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
+			return CodeGen::isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
 		}
 
@@ -992,5 +993,5 @@
 
 			function = funcDecl;
-			isCtor = isConstructor( function->get_name() );
+			isCtor = CodeGen::isConstructor( function->get_name() );
 			if ( checkWarnings( function ) ) {
 				FunctionType * type = function->get_functionType();
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 53a8e68bb29ee1058f8e4557c98ee2f853273859)
+++ src/InitTweak/GenInit.cc	(revision bff227f73387fd7ed67a8a31545259b27d4ddc24)
@@ -21,4 +21,5 @@
 
 #include "Common/PassVisitor.h"
+#include "CodeGen/OperatorTable.h"
 
 #include "GenPoly/DeclMutator.h"
@@ -235,5 +236,5 @@
 	void CtorDtor::handleDWT( DeclarationWithType * dwt ) {
 		// if this function is a user-defined constructor or destructor, mark down the type as "managed"
-		if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && isCtorDtor( dwt->get_name() ) ) {
+		if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) {
 			std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters();
 			assert( ! params.empty() );
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 53a8e68bb29ee1058f8e4557c98ee2f853273859)
+++ src/InitTweak/InitTweak.h	(revision bff227f73387fd7ed67a8a31545259b27d4ddc24)
@@ -26,10 +26,4 @@
 // helper functions for initialization
 namespace InitTweak {
-	bool isConstructor( const std::string & );
-	bool isDestructor( const std::string & );
-	bool isAssignment( const std::string & );
-	bool isCtorDtor( const std::string & );
-	bool isCtorDtorAssign( const std::string & );
-
 	FunctionDecl * isAssignment( Declaration * decl );
 	FunctionDecl * isDestructor( Declaration * decl );
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 53a8e68bb29ee1058f8e4557c98ee2f853273859)
+++ src/SymTab/Autogen.cc	(revision bff227f73387fd7ed67a8a31545259b27d4ddc24)
@@ -21,4 +21,5 @@
 #include "SynTree/TypeSubstitution.h"
 #include "Common/utility.h"
+#include "CodeGen/OperatorTable.h"
 #include "AddVisit.h"
 #include "MakeLibCfa.h"
@@ -223,5 +224,5 @@
 			FunctionType * ftype = data.genType( refType );
 
-			if(concurrent_type && InitTweak::isDestructor( data.fname )) {
+			if(concurrent_type && CodeGen::isDestructor( data.fname )) {
 				ftype->get_parameters().front()->get_type()->set_mutex( true );
 			}
@@ -407,5 +408,5 @@
 
 		// field ctors are only generated if default constructor and copy constructor are both generated
-		unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return InitTweak::isConstructor( dcl->get_name() ); } );
+		unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } );
 
 		if ( functionNesting == 0 ) {
@@ -422,10 +423,10 @@
 			// generate appropriate calls to member ctor, assignment
 			// destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor
-			if ( ! InitTweak::isDestructor( dcl->get_name() ) ) {
+			if ( ! CodeGen::isDestructor( dcl->get_name() ) ) {
 				makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl, isDynamicLayout );
 			} else {
 				makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, isDynamicLayout, false );
 			}
-			if ( InitTweak::isAssignment( dcl->get_name() ) ) {
+			if ( CodeGen::isAssignment( dcl->get_name() ) ) {
 				// assignment needs to return a value
 				FunctionType * assignType = dcl->get_functionType();
@@ -486,5 +487,5 @@
 
 		makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) );
-		if ( InitTweak::isAssignment( funcDecl->get_name() ) ) {
+		if ( CodeGen::isAssignment( funcDecl->get_name() ) ) {
 			// also generate return statement in assignment
 			funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 53a8e68bb29ee1058f8e4557c98ee2f853273859)
+++ src/SymTab/Indexer.cc	(revision bff227f73387fd7ed67a8a31545259b27d4ddc24)
@@ -26,4 +26,6 @@
 
 #include "Common/utility.h"
+
+#include "CodeGen/OperatorTable.h"
 
 #include "ResolvExpr/typeops.h"
@@ -112,5 +114,5 @@
 	void Indexer::removeSpecialOverrides( const std::string &id, std::list< DeclarationWithType * > & out ) const {
 		// only need to perform this step for constructors, destructors, and assignment functions
-		if ( ! InitTweak::isCtorDtorAssign( id ) ) return;
+		if ( ! CodeGen::isCtorDtorAssign( id ) ) return;
 
 		// helpful data structure
@@ -140,5 +142,5 @@
 				decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
 				existsUserDefinedFunc = existsUserDefinedFunc || isUserDefinedFunc;
-				existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && InitTweak::isConstructor( function->get_name() ) );
+				existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && CodeGen::isConstructor( function->get_name() ) );
 				existsUserDefinedDtor = existsUserDefinedDtor || (isUserDefinedFunc && isDtor);
 				existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 53a8e68bb29ee1058f8e4557c98ee2f853273859)
+++ src/SymTab/Validate.cc	(revision bff227f73387fd7ed67a8a31545259b27d4ddc24)
@@ -43,4 +43,5 @@
 
 #include "CodeGen/CodeGenerator.h"
+#include "CodeGen/OperatorTable.h"
 
 #include "Common/PassVisitor.h"
@@ -52,6 +53,4 @@
 
 #include "GenPoly/DeclMutator.h"
-
-#include "InitTweak/InitTweak.h"
 
 #include "AddVisit.h"
@@ -827,5 +826,5 @@
 		std::list< DeclarationWithType * > &params = funcType->get_parameters();
 
-		if ( InitTweak::isCtorDtorAssign( funcDecl->get_name() ) ) {
+		if ( CodeGen::isCtorDtorAssign( funcDecl->get_name() ) ) { // TODO: also check /=, etc.
 			if ( params.size() == 0 ) {
 				throw SemanticError( "Constructors, destructors, and assignment functions require at least one parameter ", funcDecl );
@@ -835,5 +834,5 @@
 				throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a reference ", funcDecl );
 			}
-			if ( InitTweak::isCtorDtor( funcDecl->get_name() ) && returnVals.size() != 0 ) {
+			if ( CodeGen::isCtorDtor( funcDecl->get_name() ) && returnVals.size() != 0 ) {
 				throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );
 			}
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision 53a8e68bb29ee1058f8e4557c98ee2f853273859)
+++ src/Tuples/TupleAssignment.cc	(revision bff227f73387fd7ed67a8a31545259b27d4ddc24)
@@ -22,4 +22,5 @@
 #include "Explode.h"
 #include "Common/SemanticError.h"
+#include "CodeGen/OperatorTable.h"
 #include "InitTweak/InitTweak.h"
 #include "InitTweak/GenInit.h"
@@ -110,9 +111,9 @@
 	void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
 		if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
-			if ( InitTweak::isCtorDtorAssign( op->get_name() ) ) {
+			if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {
 				fname = op->get_name();
 				for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
 					if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal
-					if ( ali->size() <= 1 && InitTweak::isAssignment( op->get_name() ) ) {
+					if ( ali->size() <= 1 && CodeGen::isAssignment( op->get_name() ) ) {
 						// what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it
 						continue;
