Index: src/GenPoly/Lvalue.cc
===================================================================
--- src/GenPoly/Lvalue.cc	(revision f8b69da714038baa1174cd4bf59e8889ef5225bc)
+++ src/GenPoly/Lvalue.cc	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -21,9 +21,9 @@
 #include "Lvalue.h"
 
+#include "InitTweak/InitTweak.h"
 #include "Parser/LinkageSpec.h"          // for Spec, isBuiltin, Intrinsic
 #include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
 #include "ResolvExpr/Unify.h"            // for unify
 #include "ResolvExpr/typeops.h"
-#include "SymTab/Autogen.h"
 #include "SymTab/Indexer.h"              // for Indexer
 #include "SynTree/Declaration.h"         // for Declaration, FunctionDecl
@@ -33,4 +33,5 @@
 #include "SynTree/Type.h"                // for PointerType, Type, FunctionType
 #include "SynTree/Visitor.h"             // for Visitor, acceptAll
+#include "Validate/FindSpecialDecls.h"   // for dereferenceOperator
 
 #if 0
@@ -44,7 +45,7 @@
 		// TODO: fold this into the general createDeref function??
 		Expression * mkDeref( Expression * arg ) {
-			if ( SymTab::dereferenceOperator ) {
+			if ( Validate::dereferenceOperator ) {
 				// note: reference depth can be arbitrarily deep here, so peel off the outermost pointer/reference, not just pointer because they are effecitvely equivalent in this pass
-				VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
+				VariableExpr * deref = new VariableExpr( Validate::dereferenceOperator );
 				deref->result = new PointerType( Type::Qualifiers(), deref->result );
 				Type * base = InitTweak::getPointerBase( arg->result );
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision f8b69da714038baa1174cd4bf59e8889ef5225bc)
+++ src/InitTweak/FixInit.cc	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -56,4 +56,5 @@
 #include "SynTree/DeclReplacer.h"      // for DeclReplacer
 #include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
+#include "Validate/FindSpecialDecls.h" // for dtorStmt, dtorStructDestroy
 
 bool ctordtorp = false; // print all debug
@@ -204,6 +205,4 @@
 			static void generate( std::list< Declaration * > & translationUnit );
 
-			void premutate( StructDecl * structDecl );
-
 			void premutate( FunctionDecl * funcDecl );
 			DeclarationWithType * postmutate( FunctionDecl * funcDecl );
@@ -227,8 +226,4 @@
 			bool isCtor = false; // true if current function is a constructor
 			StructDecl * structDecl = nullptr;
-
-			// special built-in functions necessary for this to work
-			StructDecl * dtorStruct = nullptr;
-			FunctionDecl * dtorStructDestroy = nullptr;
 		};
 
@@ -1019,10 +1014,4 @@
 		}
 
-		void GenStructMemberCalls::premutate( StructDecl * structDecl ) {
-			if ( ! dtorStruct && structDecl->name == "__Destructor" ) {
-				dtorStruct = structDecl;
-			}
-		}
-
 		void GenStructMemberCalls::premutate( FunctionDecl * funcDecl ) {
 			GuardValue( function );
@@ -1037,9 +1026,4 @@
 			unhandled.clear();
 			usedUninit.clear();
-
-			if ( ! dtorStructDestroy && funcDecl->name == "__destroy_Destructor" ) {
-				dtorStructDestroy = funcDecl;
-				return;
-			}
 
 			function = funcDecl;
@@ -1053,5 +1037,4 @@
 				if ( structType ) {
 					structDecl = structType->get_baseStruct();
-					if ( structDecl == dtorStruct ) return;
 					for ( Declaration * member : structDecl->get_members() ) {
 						if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
@@ -1127,10 +1110,13 @@
 								// function->get_statements()->push_back( callStmt );
 
+								// Optimization: do not need to call intrinsic destructors on members
+								if ( isIntrinsicSingleArgCallStmt( callStmt ) ) continue;;
+
 								// __Destructor _dtor0 = { (void *)&b.a1, (void (*)(void *)_destroy_A };
 								std::list< Statement * > stmtsToAdd;
 
 								static UniqueName memberDtorNamer = { "__memberDtor" };
-								assertf( dtorStruct, "builtin __Destructor not found." );
-								assertf( dtorStructDestroy, "builtin __destroy_Destructor not found." );
+								assertf( Validate::dtorStruct, "builtin __Destructor not found." );
+								assertf( Validate::dtorStructDestroy, "builtin __destroy_Destructor not found." );
 
 								Expression * thisExpr = new CastExpr( new AddressExpr( new VariableExpr( thisParam ) ), new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ) );
@@ -1142,7 +1128,7 @@
 								Type * dtorType = new PointerType( Type::Qualifiers(), dtorFtype );
 
-								ObjectDecl * destructor = ObjectDecl::newObject( memberDtorNamer.newName(), new StructInstType( Type::Qualifiers(), dtorStruct ), new ListInit( { new SingleInit( thisExpr ), new SingleInit( new CastExpr( dtorExpr, dtorType ) ) } ) );
+								ObjectDecl * destructor = ObjectDecl::newObject( memberDtorNamer.newName(), new StructInstType( Type::Qualifiers(), Validate::dtorStruct ), new ListInit( { new SingleInit( thisExpr ), new SingleInit( new CastExpr( dtorExpr, dtorType ) ) } ) );
 								function->statements->push_front( new DeclStmt( destructor ) );
-								destructor->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorStructDestroy ) } ) );
+								destructor->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( Validate::dtorStructDestroy ) } ) );
 
 								function->statements->kids.splice( function->statements->kids.begin(), stmtsToAdd );
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision f8b69da714038baa1174cd4bf59e8889ef5225bc)
+++ src/InitTweak/GenInit.cc	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -15,31 +15,32 @@
 #include "GenInit.h"
 
-#include <stddef.h>                // for NULL
-#include <algorithm>               // for any_of
-#include <cassert>                 // for assert, strict_dynamic_cast, assertf
-#include <iterator>                // for back_inserter, inserter, back_inse...
-#include <list>                    // for _List_iterator, list
+#include <stddef.h>                    // for NULL
+#include <algorithm>                   // for any_of
+#include <cassert>                     // for assert, strict_dynamic_cast, assertf
+#include <iterator>                    // for back_inserter, inserter, back_inse...
+#include <list>                        // for _List_iterator, list
 
 #include "CodeGen/OperatorTable.h"
-#include "Common/PassVisitor.h"    // for PassVisitor, WithGuards, WithShort...
-#include "Common/SemanticError.h"  // for SemanticError
-#include "Common/UniqueName.h"     // for UniqueName
-#include "Common/utility.h"        // for ValueGuard, maybeClone
-#include "GenPoly/GenPoly.h"       // for getFunctionType, isPolyType
-#include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::const_iter...
-#include "InitTweak.h"             // for isConstExpr, InitExpander, checkIn...
-#include "Parser/LinkageSpec.h"    // for isOverridable, C
+#include "Common/PassVisitor.h"        // for PassVisitor, WithGuards, WithShort...
+#include "Common/SemanticError.h"      // for SemanticError
+#include "Common/UniqueName.h"         // for UniqueName
+#include "Common/utility.h"            // for ValueGuard, maybeClone
+#include "GenPoly/GenPoly.h"           // for getFunctionType, isPolyType
+#include "GenPoly/ScopedSet.h"         // for ScopedSet, ScopedSet<>::const_iter...
+#include "InitTweak.h"                 // for isConstExpr, InitExpander, checkIn...
+#include "Parser/LinkageSpec.h"        // for isOverridable, C
 #include "ResolvExpr/Resolver.h"
-#include "SymTab/Autogen.h"        // for genImplicitCall, SizeType
-#include "SymTab/Mangler.h"        // for Mangler
-#include "SynTree/Declaration.h"   // for ObjectDecl, DeclarationWithType
-#include "SynTree/Expression.h"    // for VariableExpr, UntypedExpr, Address...
-#include "SynTree/Initializer.h"   // for ConstructorInit, SingleInit, Initi...
-#include "SynTree/Label.h"         // for Label
-#include "SynTree/Mutator.h"       // for mutateAll
-#include "SynTree/Statement.h"     // for CompoundStmt, ImplicitCtorDtorStmt
-#include "SynTree/Type.h"          // for Type, ArrayType, Type::Qualifiers
-#include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
-#include "Tuples/Tuples.h"         // for maybeImpure
+#include "SymTab/Autogen.h"            // for genImplicitCall
+#include "SymTab/Mangler.h"            // for Mangler
+#include "SynTree/Declaration.h"       // for ObjectDecl, DeclarationWithType
+#include "SynTree/Expression.h"        // for VariableExpr, UntypedExpr, Address...
+#include "SynTree/Initializer.h"       // for ConstructorInit, SingleInit, Initi...
+#include "SynTree/Label.h"             // for Label
+#include "SynTree/Mutator.h"           // for mutateAll
+#include "SynTree/Statement.h"         // for CompoundStmt, ImplicitCtorDtorStmt
+#include "SynTree/Type.h"              // for Type, ArrayType, Type::Qualifiers
+#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
+#include "Tuples/Tuples.h"             // for maybeImpure
+#include "Validate/FindSpecialDecls.h" // for SizeType
 
 namespace InitTweak {
@@ -186,5 +187,5 @@
 
 			// need to resolve array dimensions in order to accurately determine if constexpr
-			ResolvExpr::findSingleExpression( arrayType->dimension, SymTab::SizeType->clone(), indexer );
+			ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
 			// array is variable-length when the dimension is not constexpr
 			arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
@@ -192,5 +193,5 @@
 			if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
 
-			ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
+			ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
 			arrayDimension->get_type()->set_const( true );
 
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision f8b69da714038baa1174cd4bf59e8889ef5225bc)
+++ src/Makefile.am	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -51,5 +51,5 @@
 AM_LDFLAGS  = @HOST_FLAGS@ -Xlinker -export-dynamic
 
-demangler_SOURCES = SymTab/demangler.cc
+demangler_SOURCES = SymTab/demangler.cc # test driver for the demangler, also useful as a sanity check that libdemangle.a is complete
 
 demangler_LDADD = libdemangle.a     # yywrap
@@ -138,5 +138,6 @@
   Tuples/TupleAssignment.cc \
   Tuples/TupleExpansion.cc \
-  Validate/HandleAttributes.cc
+  Validate/HandleAttributes.cc \
+  Validate/FindSpecialDecls.cc
 
 MAINTAINERCLEANFILES += ${libdir}/${notdir ${cfa_cpplib_PROGRAMS}}
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision f8b69da714038baa1174cd4bf59e8889ef5225bc)
+++ src/Makefile.in	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -212,5 +212,6 @@
 	Tuples/Explode.$(OBJEXT) Tuples/TupleAssignment.$(OBJEXT) \
 	Tuples/TupleExpansion.$(OBJEXT) \
-	Validate/HandleAttributes.$(OBJEXT)
+	Validate/HandleAttributes.$(OBJEXT) \
+	Validate/FindSpecialDecls.$(OBJEXT)
 libdemangle_a_OBJECTS = $(am_libdemangle_a_OBJECTS)
 am__installdirs = "$(DESTDIR)$(cfa_cpplibdir)"
@@ -285,4 +286,5 @@
 	Tuples/TupleExpansion.$(OBJEXT) Tuples/Explode.$(OBJEXT) \
 	Validate/HandleAttributes.$(OBJEXT) \
+	Validate/FindSpecialDecls.$(OBJEXT) \
 	Virtual/ExpandCasts.$(OBJEXT)
 am____driver_cfa_cpp_OBJECTS = $(am__objects_1)
@@ -566,5 +568,5 @@
 	Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc \
 	Tuples/Explode.cc Validate/HandleAttributes.cc \
-	Virtual/ExpandCasts.cc
+	Validate/FindSpecialDecls.cc Virtual/ExpandCasts.cc
 MAINTAINERCLEANFILES = ${libdir}/${notdir ${cfa_cpplib_PROGRAMS}}
 MOSTLYCLEANFILES = Parser/parser.hh Parser/parser.output
@@ -580,5 +582,5 @@
 AM_CXXFLAGS = @HOST_FLAGS@ -Wno-deprecated -Wall -Wextra -DDEBUG_ALL -I./Parser -I$(srcdir)/Parser -I$(srcdir)/include -DYY_NO_INPUT -O2 -g -std=c++14
 AM_LDFLAGS = @HOST_FLAGS@ -Xlinker -export-dynamic
-demangler_SOURCES = SymTab/demangler.cc
+demangler_SOURCES = SymTab/demangler.cc # test driver for the demangler, also useful as a sanity check that libdemangle.a is complete
 demangler_LDADD = libdemangle.a     # yywrap
 noinst_LIBRARIES = libdemangle.a
@@ -665,5 +667,6 @@
   Tuples/TupleAssignment.cc \
   Tuples/TupleExpansion.cc \
-  Validate/HandleAttributes.cc
+  Validate/HandleAttributes.cc \
+  Validate/FindSpecialDecls.cc
 
 all: $(BUILT_SOURCES)
@@ -942,4 +945,6 @@
 	@: > Validate/$(DEPDIR)/$(am__dirstamp)
 Validate/HandleAttributes.$(OBJEXT): Validate/$(am__dirstamp) \
+	Validate/$(DEPDIR)/$(am__dirstamp)
+Validate/FindSpecialDecls.$(OBJEXT): Validate/$(am__dirstamp) \
 	Validate/$(DEPDIR)/$(am__dirstamp)
 
@@ -1203,4 +1208,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/TupleAssignment.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/TupleExpansion.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@Validate/$(DEPDIR)/FindSpecialDecls.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@Validate/$(DEPDIR)/HandleAttributes.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@Virtual/$(DEPDIR)/ExpandCasts.Po@am__quote@
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision f8b69da714038baa1174cd4bf59e8889ef5225bc)
+++ src/ResolvExpr/Resolver.cc	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -31,5 +31,4 @@
 #include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
 #include "Resolver.h"
-#include "SymTab/Autogen.h"              // for SizeType
 #include "SymTab/Indexer.h"              // for Indexer
 #include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
@@ -43,4 +42,5 @@
 #include "typeops.h"                     // for extractResultType
 #include "Unify.h"                       // for unify
+#include "Validate/FindSpecialDecls.h"   // for SizeType
 
 using namespace std;
@@ -374,5 +374,5 @@
 	void Resolver::handlePtrType( PtrType * type ) {
 		if ( type->get_dimension() ) {
-			findSingleExpression( type->dimension, SymTab::SizeType->clone(), indexer );
+			findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
 		}
 	}
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision f8b69da714038baa1174cd4bf59e8889ef5225bc)
+++ src/SymTab/Autogen.cc	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -41,6 +41,4 @@
 
 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 {
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision f8b69da714038baa1174cd4bf59e8889ef5225bc)
+++ src/SymTab/Autogen.h	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -36,12 +36,4 @@
 	/// returns true if obj's name is the empty string and it has a bitfield width
 	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.
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision f8b69da714038baa1174cd4bf59e8889ef5225bc)
+++ src/SymTab/Validate.cc	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -75,4 +75,5 @@
 #include "SynTree/Visitor.h"           // for Visitor
 #include "Validate/HandleAttributes.h" // for handleAttributes
+#include "Validate/FindSpecialDecls.h" // for FindSpecialDecls
 
 class CompoundStmt;
@@ -287,9 +288,4 @@
 	};
 
-	FunctionDecl * dereferenceOperator = nullptr;
-	struct FindSpecialDeclarations final {
-		void previsit( FunctionDecl * funcDecl );
-	};
-
 	void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
 		PassVisitor<EnumAndPointerDecay> epc;
@@ -298,5 +294,4 @@
 		PassVisitor<CompoundLiteral> compoundliteral;
 		PassVisitor<ValidateGenericParameters> genericParams;
-		PassVisitor<FindSpecialDeclarations> finder;
 		PassVisitor<LabelAddressFixer> labelAddrFixer;
 		PassVisitor<HoistTypeDecls> hoistDecls;
@@ -325,5 +320,5 @@
 		FixObjectType::fix( translationUnit );
 		ArrayLength::computeLength( translationUnit );
-		acceptAll( translationUnit, finder ); // xxx - remove this pass soon
+		Validate::findSpecialDecls( translationUnit );
 		mutateAll( translationUnit, labelAddrFixer );
 		Validate::handleAttributes( translationUnit );
@@ -901,9 +896,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 );
 		}
 	}
@@ -1293,5 +1288,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
@@ -1330,22 +1325,4 @@
 		return addrExpr;
 	}
-
-	void FindSpecialDeclarations::previsit( FunctionDecl * funcDecl ) {
-		if ( ! dereferenceOperator ) {
-			// find and remember the intrinsic dereference operator for object pointers
-			if ( funcDecl->name == "*?" && funcDecl->linkage == LinkageSpec::Intrinsic ) {
-				FunctionType * ftype = funcDecl->type;
-				if ( ftype->parameters.size() == 1 ) {
-					PointerType * ptrType = strict_dynamic_cast<PointerType *>( ftype->parameters.front()->get_type() );
-					if ( ptrType->base->get_qualifiers() == Type::Qualifiers() ) {
-						TypeInstType * inst = dynamic_cast<TypeInstType *>( ptrType->base );
-						if ( inst && ! inst->get_isFtype() ) {
-							dereferenceOperator = funcDecl;
-						}
-					}
-				}
-			}
-		}
-	}
 } // namespace SymTab
 
Index: src/Validate/FindSpecialDecls.cc
===================================================================
--- src/Validate/FindSpecialDecls.cc	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
+++ src/Validate/FindSpecialDecls.cc	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -0,0 +1,100 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// FindSpecialDecls.cc --
+//
+// Author           : Rob Schluntz
+// Created On       : Thu Aug 30 09:49:43 2018
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Aug 30 09:55:25 2018
+// Update Count     : 2
+//
+
+#include "FindSpecialDecls.h"
+
+#include "Common/PassVisitor.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+
+// NOTE: currently, it is assumed that every special declaration occurs at the top-level,
+// so function bodies, aggregate bodies, object initializers, etc. are not visited.
+// If this assumption changes, e.g., with the introduction of namespaces, remove the visit_children assignments.
+
+namespace Validate {
+	Type * SizeType = nullptr;
+  FunctionDecl * dereferenceOperator = nullptr;
+  StructDecl * dtorStruct = nullptr;
+  FunctionDecl * dtorStructDestroy = nullptr;
+
+	namespace {
+		struct FindSpecialDecls final : public WithShortCircuiting {
+			void previsit( ObjectDecl * objDecl );
+			void previsit( FunctionDecl * funcDecl );
+			void previsit( StructDecl * structDecl );
+			void previsit( UnionDecl * unionDecl );
+			void previsit( EnumDecl * enumDecl );
+			void previsit( TraitDecl * traitDecl );
+		};
+	} // namespace
+
+	void findSpecialDecls( std::list< Declaration * > &translationUnit ) {
+		PassVisitor<FindSpecialDecls> finder;
+		acceptAll( translationUnit, finder );
+		// TODO: conditionally generate 'fake' declarations for missing features, so that
+		// translation can proceed in the event that builtins, prelude, etc. are missing.
+	}
+
+	namespace {
+		void FindSpecialDecls::previsit( ObjectDecl * ) {
+			visit_children = false;
+		}
+
+		void FindSpecialDecls::previsit( FunctionDecl * funcDecl ) {
+			visit_children = false;
+			if ( ! dereferenceOperator && funcDecl->name == "*?" && funcDecl->linkage == LinkageSpec::Intrinsic ) {
+				// find and remember the intrinsic dereference operator for object pointers
+				FunctionType * ftype = funcDecl->type;
+				if ( ftype->parameters.size() == 1 ) {
+					PointerType * ptrType = strict_dynamic_cast<PointerType *>( ftype->parameters.front()->get_type() );
+					if ( ptrType->base->get_qualifiers() == Type::Qualifiers() ) {
+						TypeInstType * inst = dynamic_cast<TypeInstType *>( ptrType->base );
+						if ( inst && ! inst->get_isFtype() ) {
+							dereferenceOperator = funcDecl;
+						}
+					}
+				}
+			} else if ( ! dtorStructDestroy && funcDecl->name == "__destroy_Destructor" ) {
+				dtorStructDestroy = funcDecl;
+			}
+		}
+
+		void FindSpecialDecls::previsit( StructDecl * structDecl ) {
+			visit_children = false;
+			if ( ! dtorStruct && structDecl->name == "__Destructor" ) {
+				dtorStruct = structDecl;
+			}
+		}
+
+		void FindSpecialDecls::previsit( UnionDecl * ) {
+			visit_children = false;
+		}
+
+		void FindSpecialDecls::previsit( EnumDecl * ) {
+			visit_children = false;
+		}
+
+		void FindSpecialDecls::previsit( TraitDecl * ) {
+			visit_children = false;
+		}
+
+	} // namespace
+} // namespace Validate
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/FindSpecialDecls.h
===================================================================
--- src/Validate/FindSpecialDecls.h	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
+++ src/Validate/FindSpecialDecls.h	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -0,0 +1,46 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// FindSpecialDeclarations.h --
+//
+// Author           : Rob Schluntz
+// Created On       : Thu Aug 30 09:49:02 2018
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Aug 30 09:51:12 2018
+// Update Count     : 2
+//
+
+#pragma once
+
+#include <list>  // for list
+
+class Declaration;
+class FunctionDecl;
+class StructDecl;
+class Type;
+
+namespace Validate {
+	/// 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;
+
+	/// special built-in functions and data structures necessary for destructor generation
+	extern StructDecl * dtorStruct;
+	extern FunctionDecl * dtorStructDestroy;
+
+	/// find and remember some of the special declarations that are useful for generating code, so that they do not have to be discovered multiple times.
+	void findSpecialDecls( std::list< Declaration * > & translationUnit );
+} // namespace Validate
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/module.mk
===================================================================
--- src/Validate/module.mk	(revision f8b69da714038baa1174cd4bf59e8889ef5225bc)
+++ src/Validate/module.mk	(revision 2bfc6b281e65c5e8bdf4d021589a170c2cb15418)
@@ -15,3 +15,4 @@
 ###############################################################################
 
-SRC += Validate/HandleAttributes.cc
+SRC += Validate/HandleAttributes.cc \
+	Validate/FindSpecialDecls.cc
