Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 69911c112f8ee63e5b034a4052592b8607062c40)
+++ src/SymTab/Validate.cc	(revision 784deab79c9d58f003b487276e5bf683364fc75c)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Validate.cc -- 
+// Validate.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 21:50:04 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Fri Nov 20 16:33:52 2015
-// Update Count     : 201
+// Last Modified On : Fri Dec 18 15:34:05 2015
+// Update Count     : 218
 //
 
@@ -63,7 +63,7 @@
 		/// Flattens nested struct types
 		static void hoistStruct( std::list< Declaration * > &translationUnit );
-  
+
 		std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
-  
+
 		virtual void visit( StructDecl *aggregateDecl );
 		virtual void visit( UnionDecl *aggregateDecl );
@@ -86,5 +86,5 @@
 	};
 
-	/// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers
+	/// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
 	class Pass1 : public Visitor {
 		typedef Visitor Parent;
@@ -107,5 +107,5 @@
 
 		const Indexer *indexer;
-  
+
 		typedef std::map< std::string, std::list< StructInstType * > > ForwardStructsType;
 		typedef std::map< std::string, std::list< UnionInstType * > > ForwardUnionsType;
@@ -132,5 +132,5 @@
 
 		std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
-  
+
 		virtual void visit( EnumDecl *enumDecl );
 		virtual void visit( StructDecl *structDecl );
@@ -142,5 +142,5 @@
 		virtual void visit( FunctionType *ftype );
 		virtual void visit( PointerType *ftype );
-  
+
 		virtual void visit( CompoundStmt *compoundStmt );
 		virtual void visit( IfStmt *ifStmt );
@@ -155,5 +155,5 @@
 	  private:
 		template< typename StmtClass > void visitStatement( StmtClass *stmt );
-  
+
 		std::list< Declaration * > declsToAdd;
 		std::set< std::string > structsDone;
@@ -161,8 +161,22 @@
 	};
 
+	class ReturnChecker : public Visitor {
+	  public:
+		/// Checks that return statements return nothing if their return type is void
+		/// and return something if the return type is non-void.
+		static void checkFunctionReturns( std::list< Declaration * > & translationUnit );
+
+	  private:
+		virtual void visit( FunctionDecl * functionDecl );
+
+		virtual void visit( ReturnStmt * returnStmt );
+
+		std::list< DeclarationWithType * > returnVals;
+	};
+
 	class EliminateTypedef : public Mutator {
 	  public:
-	  EliminateTypedef() : scopeLevel( 0 ) {}
-	    /// Replaces typedefs by forward declarations
+		EliminateTypedef() : scopeLevel( 0 ) {}
+		/// Replaces typedefs by forward declarations
 		static void eliminateTypedef( std::list< Declaration * > &translationUnit );
 	  private:
@@ -196,8 +210,9 @@
 		acceptAll( translationUnit, pass1 );
 		acceptAll( translationUnit, pass2 );
+		ReturnChecker::checkFunctionReturns( translationUnit );
 		AutogenerateRoutines::autogenerateRoutines( translationUnit );
 		acceptAll( translationUnit, pass3 );
 	}
-	
+
 	void validateType( Type *type, const Indexer *indexer ) {
 		Pass1 pass1;
@@ -307,5 +322,5 @@
 	void Pass1::visit( EnumDecl *enumDecl ) {
 		// Set the type of each member of the enumeration to be EnumConstant
-  
+
 		for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
 			ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i );
@@ -331,5 +346,5 @@
 				++i;
 				func->get_parameters().erase( j );
-				if ( i != end ) { 
+				if ( i != end ) {
 					throw SemanticError( "invalid type void in function type ", func );
 				} // if
@@ -512,15 +527,15 @@
 
 		UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
-  
+
 		UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
 		derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
-  
+
 		// do something special for unnamed members
 		Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
 		assignExpr->get_args().push_back( dstselect );
-  
+
 		Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
 		assignExpr->get_args().push_back( srcselect );
-  
+
 		*out++ = new ExprStmt( noLabels, assignExpr );
 	}
@@ -529,11 +544,11 @@
 	void makeArrayAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) {
 		static UniqueName indexName( "_index" );
-  
+
 		// for a flexible array member nothing is done -- user must define own assignment
 		if ( ! array->get_dimension() ) return;
-  
+
 		ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 );
 		*out++ = new DeclStmt( noLabels, index );
-  
+
 		UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
 		init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
@@ -542,17 +557,17 @@
 		std::list<Statement *> initList;
 		initList.push_back( initStmt );
-  
+
 		UntypedExpr *cond = new UntypedExpr( new NameExpr( "?<?" ) );
 		cond->get_args().push_back( new VariableExpr( index ) );
 		cond->get_args().push_back( array->get_dimension()->clone() );
-  
+
 		UntypedExpr *inc = new UntypedExpr( new NameExpr( "++?" ) );
 		inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
-  
+
 		UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
-  
+
 		UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
 		derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
-  
+
 		Expression *dstselect = new MemberExpr( member, derefExpr );
 		UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
@@ -560,5 +575,5 @@
 		dstIndex->get_args().push_back( new VariableExpr( index ) );
 		assignExpr->get_args().push_back( dstIndex );
-  
+
 		Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
 		UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
@@ -566,13 +581,13 @@
 		srcIndex->get_args().push_back( new VariableExpr( index ) );
 		assignExpr->get_args().push_back( srcIndex );
-  
+
 		*out++ = new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, assignExpr ) );
 	}
 
-	//E ?=?(E volatile*, int), 
+	//E ?=?(E volatile*, int),
 	//  ?=?(E _Atomic volatile*, int);
 	void makeEnumAssignment( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
 		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
-  
+
 		ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
 		assignType->get_returnVals().push_back( returnVal );
@@ -593,5 +608,5 @@
 		// E ?=?(E volatile *, int)
 		assignType2->get_parameters().push_back( dstParam->clone() );
-		BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt); 
+		BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt);
 		ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 );
 		assignType2->get_parameters().push_back( srcParam2 );
@@ -645,11 +660,11 @@
 			structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
 		}
-  
+
 		ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
 		assignType->get_returnVals().push_back( returnVal );
-  
+
 		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
 		assignType->get_parameters().push_back( dstParam );
-  
+
 		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
 		assignType->get_parameters().push_back( srcParam );
@@ -659,8 +674,8 @@
 		FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
 		assignDecl->fixUniqueId();
-  
+
 		for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
 			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
-				// query the type qualifiers of this field and skip assigning it if it is marked const. 
+				// query the type qualifiers of this field and skip assigning it if it is marked const.
 				// If it is an array type, we need to strip off the array layers to find its qualifiers.
 				Type * type = dwt->get_type();
@@ -682,5 +697,5 @@
 		} // for
 		assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
-  
+
 		return assignDecl;
 	}
@@ -697,19 +712,19 @@
 			unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
 		}
-  
+
 		ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
 		assignType->get_returnVals().push_back( returnVal );
-  
+
 		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
 		assignType->get_parameters().push_back( dstParam );
-  
+
 		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
 		assignType->get_parameters().push_back( srcParam );
-  
+
 		// Routines at global scope marked "static" to prevent multiple definitions is separate translation units
 		// because each unit generates copies of the default routines for each aggregate.
 		FunctionDecl *assignDecl = new FunctionDecl( "?=?",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
 		assignDecl->fixUniqueId();
-  
+
 		UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
 		copy->get_args().push_back( new VariableExpr( dstParam ) );
@@ -719,5 +734,5 @@
 		assignDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, copy ) );
 		assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
-  
+
 		return assignDecl;
 	}
@@ -727,5 +742,5 @@
 			EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
 			// enumInst->set_baseEnum( enumDecl );
-			// declsToAdd.push_back( 
+			// declsToAdd.push_back(
 			makeEnumAssignment( enumDecl, enumInst, functionNesting, declsToAdd );
 		}
@@ -836,4 +851,25 @@
 	}
 
+	void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) {
+		ReturnChecker checker;
+		acceptAll( translationUnit, checker );
+	}
+
+	void ReturnChecker::visit( FunctionDecl * functionDecl ) {
+		std::list< DeclarationWithType * > oldReturnVals = returnVals;
+		returnVals = functionDecl->get_functionType()->get_returnVals();
+		Visitor::visit( functionDecl );
+		returnVals = oldReturnVals;
+	}
+
+	void ReturnChecker::visit( ReturnStmt * returnStmt ) {
+		if ( returnStmt->get_expr() == NULL && returnVals.size() != 0 ) {
+			throw SemanticError( "Non-void function returns no values: " , returnStmt );
+		} else if ( returnStmt->get_expr() != NULL && returnVals.size() == 0 ) {
+			throw SemanticError( "void function returns values: " , returnStmt );
+		}
+	}
+
+
 	bool isTypedef( Declaration *decl ) {
 		return dynamic_cast< TypedefDecl * >( decl );
@@ -847,5 +883,5 @@
 
 	Type *EliminateTypedef::mutate( TypeInstType * typeInst ) {
-		// instances of typedef types will come here. If it is an instance 
+		// instances of typedef types will come here. If it is an instance
 		// of a typdef type, link the instance to its actual type.
 		TypedefMap::const_iterator def = typedefNames.find( typeInst->get_name() );
@@ -871,5 +907,5 @@
 		Declaration *ret = Mutator::mutate( tyDecl );
 		if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
-			// typedef to the same name from the same scope 
+			// typedef to the same name from the same scope
 			// must be from the same type
 
