Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 25fcb84f4d4e0dd6a778f8ce5a1bb0777e946a31)
+++ src/SymTab/Indexer.cc	(revision 0a75b775e51c0c657af0600d4f564720e44fd5fc)
@@ -106,19 +106,14 @@
 		if ( ! CodeGen::isCtorDtorAssign( id ) ) return;
 
-		// helpful data structure
+		// helpful data structure to organize properties for a type
 		struct ValueType {
-			struct DeclBall {
+			struct DeclBall { // properties for this particular decl
 				IdData decl;
-				bool isUserDefinedFunc; // properties for this particular decl
-				bool isDefaultCtor;
-				bool isDtor;
+				bool isUserDefinedFunc;
 				bool isCopyFunc;
 			};
 			// properties for this type
-			bool existsUserDefinedFunc = false;    // any user-defined function found
-			bool existsUserDefinedCtor = false;    // any user-defined constructor found
-			bool existsUserDefinedDtor = false;    // any user-defined destructor found
 			bool existsUserDefinedCopyFunc = false;    // user-defined copy ctor found
-			bool existsUserDefinedDefaultCtor = false; // user-defined default ctor found
+			BaseSyntaxNode * deleteStmt = nullptr;     // non-null if a user-defined function is found
 			std::list< DeclBall > decls;
 
@@ -127,14 +122,13 @@
 			ValueType & operator+=( IdData data ) {
 				DeclarationWithType * function = data.id;
-				bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->get_linkage() );
-				bool isDefaultCtor = InitTweak::isDefaultConstructor( function );
-				bool isDtor = InitTweak::isDestructor( function );
-				bool isCopyFunc = InitTweak::isCopyFunction( function, function->get_name() );
-				decls.push_back( DeclBall{ data, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
-				existsUserDefinedFunc = existsUserDefinedFunc || isUserDefinedFunc;
-				existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && CodeGen::isConstructor( function->get_name() ) );
-				existsUserDefinedDtor = existsUserDefinedDtor || (isUserDefinedFunc && isDtor);
+				bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage );
+				bool isCopyFunc = InitTweak::isCopyFunction( function, function->name );
+				decls.push_back( DeclBall{ data, isUserDefinedFunc, isCopyFunc } );
 				existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
-				existsUserDefinedDefaultCtor = existsUserDefinedDefaultCtor || (isUserDefinedFunc && isDefaultCtor);
+				if ( isUserDefinedFunc && ! data.deleteStmt ) {
+					// any user-defined function can act as an implicit delete statement for generated constructors.
+					// a delete stmt should not act as an implicit delete statement.
+					deleteStmt = data.id;
+				}
 				return *this;
 			}
@@ -160,21 +154,23 @@
 
 		// if a type contains user defined ctor/dtor/assign, then special rules trigger, which determine
-		// the set of ctor/dtor/assign that are seen by the requester. In particular, if the user defines
-		// a default ctor, then the generated default ctor should never be seen, likewise for copy ctor
-		// and dtor. If the user defines any ctor/dtor, then no generated field ctors should be seen.
-		// If the user defines any ctor then the generated default ctor should not be seen (intrinsic default
-		// ctor must be overridden exactly).
+		// the set of ctor/dtor/assign that can be used  by the requester. In particular, if the user defines
+		// a default ctor, then the generated default ctor is unavailable, likewise for copy ctor
+		// and dtor. If the user defines any ctor/dtor, then no generated field ctors are available.
+		// If the user defines any ctor then the generated default ctor is unavailable (intrinsic default
+		// ctor must be overridden exactly). If the user defines anything that looks like a copy constructor,
+		// then the generated copy constructor is unavailable, and likewise for the assignment operator.
 		for ( std::pair< const std::string, ValueType > & pair : funcMap ) {
 			ValueType & val = pair.second;
 			for ( ValueType::DeclBall ball : val.decls ) {
-				bool noUserDefinedFunc = ! val.existsUserDefinedFunc;
-				bool isUserDefinedFunc = ball.isUserDefinedFunc;
-				bool isAcceptableDefaultCtor = (! val.existsUserDefinedCtor || (! val.existsUserDefinedDefaultCtor && ball.decl.id->linkage == LinkageSpec::Intrinsic)) && ball.isDefaultCtor; // allow default constructors only when no user-defined constructors exist, except in the case of intrinsics, which require exact overrides
-				bool isAcceptableCopyFunc = ! val.existsUserDefinedCopyFunc && ball.isCopyFunc; // handles copy ctor and assignment operator
-				bool isAcceptableDtor = ! val.existsUserDefinedDtor && ball.isDtor;
-				if ( noUserDefinedFunc || isUserDefinedFunc || isAcceptableDefaultCtor || isAcceptableCopyFunc || isAcceptableDtor ) {
-					// decl conforms to the rules described above, so it should be seen by the requester
-					out.push_back( ball.decl );
+				bool isNotUserDefinedFunc = ! ball.isUserDefinedFunc && ball.decl.id->linkage != LinkageSpec::Intrinsic;
+				bool isCopyFunc = ball.isCopyFunc;
+				bool existsUserDefinedCopyFunc = val.existsUserDefinedCopyFunc;
+				// only implicitly delete non-user defined functions that are  not intrinsic, and are
+				// not copy functions (assignment or copy constructor), unless a user-defined copy function exists.
+				// deleteStmt will be non-null only if a user-defined function is found.
+				if (isNotUserDefinedFunc && (! isCopyFunc || existsUserDefinedCopyFunc)) {
+					ball.decl.deleteStmt = val.deleteStmt;
 				}
+				out.push_back( ball.decl );
 			}
 		}
