Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 20550989ac1a8e2e7bd901d050c04cd0baf675a6)
+++ src/SymTab/Validate.cc	(revision ed8a0d2378d457af8e5826c9d961a9d400fcc6c1)
@@ -240,13 +240,13 @@
 		ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
 		acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
+		acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist
+		VerifyCtorDtorAssign::verify( translationUnit );  // must happen before autogen, because autogen examines existing ctor/dtors
 		Concurrency::applyKeywords( translationUnit );
 		autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecayPass
 		Concurrency::implementMutexFuncs( translationUnit );
 		Concurrency::implementThreadStarter( translationUnit );
-		acceptAll( translationUnit, epc );
 		ReturnChecker::checkFunctionReturns( translationUnit );
 		compoundliteral.mutateDeclarationList( translationUnit );
 		acceptAll( translationUnit, pass3 );
-		VerifyCtorDtorAssign::verify( translationUnit );
 		ArrayLength::computeLength( translationUnit );
 	}
@@ -817,5 +817,6 @@
 				throw SemanticError( "Constructors, destructors, and assignment functions require at least one parameter ", funcDecl );
 			}
-			if ( ! dynamic_cast< PointerType * >( params.front()->get_type() ) ) {
+			PointerType * ptrType = dynamic_cast< PointerType * >( params.front()->get_type() );
+			if ( ! ptrType || ptrType->is_array() ) {
 				throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a pointer ", funcDecl );
 			}
Index: src/SynTree/PointerType.cc
===================================================================
--- src/SynTree/PointerType.cc	(revision 20550989ac1a8e2e7bd901d050c04cd0baf675a6)
+++ src/SynTree/PointerType.cc	(revision ed8a0d2378d457af8e5826c9d961a9d400fcc6c1)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// PointerType.cc -- 
+// PointerType.cc --
 //
 // Author           : Richard C. Bilson
@@ -38,14 +38,19 @@
 void PointerType::print( std::ostream &os, int indent ) const {
 	Type::print( os, indent );
-	os << "pointer to ";
-	if ( isStatic ) {
-		os << "static ";
-	} // if
-	if ( isVarLen ) {
-		os << "variable length array of ";
-	} else if ( dimension ) {
-		os << "array of ";
-		dimension->print( os, indent );
-	} // if
+	if ( ! is_array() ) {
+		os << "pointer to ";
+	} else {
+		os << "decayed ";
+		if ( isStatic ) {
+			os << "static ";
+		} // if
+		if ( isVarLen ) {
+			os << "variable length array of ";
+		} else if ( dimension ) {
+			os << "array of ";
+			dimension->print( os, indent );
+			os << " ";
+		} // if
+	}
 	if ( base ) {
 		base->print( os, indent );
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision 20550989ac1a8e2e7bd901d050c04cd0baf675a6)
+++ src/SynTree/Type.h	(revision ed8a0d2378d457af8e5826c9d961a9d400fcc6c1)
@@ -247,4 +247,6 @@
 	void set_isStatic( bool newValue ) { isStatic = newValue; }
 
+	bool is_array() const { return isStatic || isVarLen || dimension; }
+
 	virtual PointerType *clone() const { return new PointerType( *this ); }
 	virtual void accept( Visitor & v ) { v.visit( this ); }
