Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 052cd7138ff5b8149b63ee8fba41fa31770761c4)
+++ src/SymTab/Autogen.cc	(revision 0161ddf025ea76d6104b602bd5613e77757b6c75)
@@ -41,9 +41,7 @@
 
 namespace SymTab {
-	Type * SizeType = 0;
-
 	/// Data used to generate functions generically. Specifically, the name of the generated function and a function which generates the routine protoype
 	struct FuncData {
-		typedef FunctionType * (*TypeGen)( Type * );
+		typedef FunctionType * (*TypeGen)( Type *, bool );
 		FuncData( const std::string & fname, const TypeGen & genType ) : fname( fname ), genType( genType ) {}
 		std::string fname;
@@ -231,8 +229,11 @@
 
 	/// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
-	FunctionType * genDefaultType( Type * paramType ) {
-		const auto & typeParams = getGenericParams( paramType );
+	FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
 		FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
-		cloneAll( typeParams, ftype->forall );
+		if ( maybePolymorphic ) {
+			// only copy in
+			const auto & typeParams = getGenericParams( paramType );
+			cloneAll( typeParams, ftype->forall );
+		}
 		ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
 		ftype->parameters.push_back( dstParam );
@@ -241,6 +242,6 @@
 
 	/// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T)
-	FunctionType * genCopyType( Type * paramType ) {
-		FunctionType *ftype = genDefaultType( paramType );
+	FunctionType * genCopyType( Type * paramType, bool maybePolymorphic ) {
+		FunctionType *ftype = genDefaultType( paramType, maybePolymorphic );
 		ObjectDecl *srcParam = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
 		ftype->parameters.push_back( srcParam );
@@ -249,6 +250,6 @@
 
 	/// given type T, generate type of assignment, i.e. function type T (*) (T *, T)
-	FunctionType * genAssignType( Type * paramType ) {
-		FunctionType *ftype = genCopyType( paramType );
+	FunctionType * genAssignType( Type * paramType, bool maybePolymorphic ) {
+		FunctionType *ftype = genCopyType( paramType, maybePolymorphic );
 		ObjectDecl *returnVal = new ObjectDecl( "_ret", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
 		ftype->returnVals.push_back( returnVal );
@@ -308,5 +309,5 @@
 		for ( const FuncData & d : data ) {
 			// generate a function (?{}, ?=?, ^?{}) based on the current FuncData.
-			FunctionType * ftype = d.genType( type );
+			FunctionType * ftype = d.genType( type, true );
 
 			// destructor for concurrent type must be mutex
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision 052cd7138ff5b8149b63ee8fba41fa31770761c4)
+++ src/SymTab/Autogen.h	(revision 0161ddf025ea76d6104b602bd5613e77757b6c75)
@@ -37,20 +37,15 @@
 	bool isUnnamedBitfield( ObjectDecl * obj );
 
-	/// size_t type - set when size_t typedef is seen. Useful in a few places,
-	/// such as in determining array dimension type
-	extern Type * SizeType;
-
-	/// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations.
-	/// Useful for creating dereference ApplicationExprs without a full resolver pass.
-	extern FunctionDecl * dereferenceOperator;
-
-	// generate the type of an assignment function for paramType
-	FunctionType * genAssignType( Type * paramType );
-
-	// generate the type of a default constructor or destructor for paramType
-	FunctionType * genDefaultType( Type * paramType );
-
-	// generate the type of a copy constructor for paramType
-	FunctionType * genCopyType( Type * paramType );
+	/// generate the type of an assignment function for paramType.
+	/// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
+	FunctionType * genAssignType( Type * paramType, bool maybePolymorphic = true );
+
+	/// generate the type of a default constructor or destructor for paramType.
+	/// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
+	FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
+
+	/// generate the type of a copy constructor for paramType.
+	/// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
+	FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
 
 	/// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 052cd7138ff5b8149b63ee8fba41fa31770761c4)
+++ src/SymTab/Validate.cc	(revision 0161ddf025ea76d6104b602bd5613e77757b6c75)
@@ -76,4 +76,5 @@
 #include "SynTree/Visitor.h"           // for Visitor
 #include "Validate/HandleAttributes.h" // for handleAttributes
+#include "Validate/FindSpecialDecls.h" // for FindSpecialDecls
 
 class CompoundStmt;
@@ -288,9 +289,4 @@
 	};
 
-	FunctionDecl * dereferenceOperator = nullptr;
-	struct FindSpecialDeclarations final {
-		void previsit( FunctionDecl * funcDecl );
-	};
-
 	void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
 		PassVisitor<EnumAndPointerDecay> epc;
@@ -299,5 +295,4 @@
 		PassVisitor<CompoundLiteral> compoundliteral;
 		PassVisitor<ValidateGenericParameters> genericParams;
-		PassVisitor<FindSpecialDeclarations> finder;
 		PassVisitor<LabelAddressFixer> labelAddrFixer;
 		PassVisitor<HoistTypeDecls> hoistDecls;
@@ -378,5 +373,5 @@
 			});
 			Stats::Time::TimeBlock("Find Special Declarations", [&]() {
-				acceptAll( translationUnit, finder ); // xxx - remove this pass soon
+				Validate::findSpecialDecls( translationUnit );
 			});
 			Stats::Time::TimeBlock("Fix Label Address", [&]() {
@@ -943,9 +938,9 @@
 		if ( eliminator.pass.typedefNames.count( "size_t" ) ) {
 			// grab and remember declaration of size_t
-			SizeType = eliminator.pass.typedefNames["size_t"].first->base->clone();
+			Validate::SizeType = eliminator.pass.typedefNames["size_t"].first->base->clone();
 		} else {
 			// xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong
 			// eventually should have a warning for this case.
-			SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
+			Validate::SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
 		}
 	}
@@ -1335,5 +1330,5 @@
 			// need to resolve array dimensions early so that constructor code can correctly determine
 			// if a type is a VLA (and hence whether its elements need to be constructed)
-			ResolvExpr::findSingleExpression( type->dimension, SymTab::SizeType->clone(), indexer );
+			ResolvExpr::findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
 
 			// must re-evaluate whether a type is a VLA, now that more information is available
@@ -1372,15 +1367,4 @@
 		return addrExpr;
 	}
-
-	void FindSpecialDeclarations::previsit( FunctionDecl * funcDecl ) {
-		if ( ! dereferenceOperator ) {
-			if ( funcDecl->get_name() == "*?" && funcDecl->get_linkage() == LinkageSpec::Intrinsic ) {
-				FunctionType * ftype = funcDecl->get_functionType();
-				if ( ftype->get_parameters().size() == 1 && ftype->get_parameters().front()->get_type()->get_qualifiers() == Type::Qualifiers() ) {
-					dereferenceOperator = funcDecl;
-				}
-			}
-		}
-	}
 } // namespace SymTab
 
