Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision a4ca48cb2a2bd7a18b74f59046bc85b612b8c212)
+++ src/ResolvExpr/Resolver.cc	(revision d67cdb749954789d84d7a8bbabc0ec601347a7bb)
@@ -40,4 +40,5 @@
 #include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
 #include "typeops.h"                     // for extractResultType
+#include "Unify.h"                       // for unify
 
 using namespace std;
@@ -71,4 +72,5 @@
 		void previsit( ThrowStmt *throwStmt );
 		void previsit( CatchStmt *catchStmt );
+		void previsit( WaitForStmt * stmt );
 
 		void previsit( SingleInit *singleInit );
@@ -93,4 +95,9 @@
 		PassVisitor<Resolver> resolver;
 		acceptAll( translationUnit, resolver );
+	}
+
+	void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) {
+		PassVisitor<Resolver> resolver( indexer );
+		maybeAccept( decl, resolver );
 	}
 
@@ -116,26 +123,26 @@
 	}
 
+	Expression * findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
+		TypeEnvironment env;
+		AlternativeFinder finder( indexer, env );
+		finder.find( untyped );
+		#if 0
+		if ( finder.get_alternatives().size() != 1 ) {
+			std::cout << "untyped expr is ";
+			untyped->print( std::cout );
+			std::cout << std::endl << "alternatives are:";
+			for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
+				i->print( std::cout );
+			} // for
+		} // if
+		#endif
+		assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );
+		Alternative &choice = finder.get_alternatives().front();
+		Expression *newExpr = choice.expr->clone();
+		finishExpr( newExpr, choice.env );
+		return newExpr;
+	}
+
 	namespace {
-		Expression *findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
-			TypeEnvironment env;
-			AlternativeFinder finder( indexer, env );
-			finder.find( untyped );
-#if 0
-			if ( finder.get_alternatives().size() != 1 ) {
-				std::cout << "untyped expr is ";
-				untyped->print( std::cout );
-				std::cout << std::endl << "alternatives are:";
-				for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
-					i->print( std::cout );
-				} // for
-			} // if
-#endif
-			assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );
-			Alternative &choice = finder.get_alternatives().front();
-			Expression *newExpr = choice.expr->clone();
-			finishExpr( newExpr, choice.env );
-			return newExpr;
-		}
-
 		bool isIntegralType( Type *type ) {
 			if ( dynamic_cast< EnumInstType * >( type ) ) {
@@ -391,4 +398,207 @@
 	}
 
+	inline void resolveAsIf( Expression *& expr, SymTab::Indexer & indexer ) {
+		if( !expr ) return;
+		Expression * newExpr = findSingleExpression( expr, indexer );
+		delete expr;
+		expr = newExpr;
+	}
+
+	inline void resolveAsType( Expression *& expr, Type * type, SymTab::Indexer & indexer ) {
+		if( !expr ) return;
+		Expression * newExpr = findSingleExpression( new CastExpr( expr, type ), indexer );
+		delete expr;
+		expr = newExpr;
+	}
+
+	template< typename iterator_t >
+	inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) {
+		while( it != end && !(*it)->get_type()->get_mutex() ) {
+			it++;
+		}
+
+		return it != end;
+	}
+
+	void Resolver::previsit( WaitForStmt * stmt ) {
+		visit_children = false;
+
+		// Resolve all clauses first
+		for( auto& clause : stmt->clauses ) {
+
+			TypeEnvironment env;
+			AlternativeFinder funcFinder( indexer, env );
+
+			// Find all alternatives for a function in canonical form
+			funcFinder.findWithAdjustment( clause.target.function );
+
+			if ( funcFinder.get_alternatives().empty() ) {
+				stringstream ss;
+				ss << "Use of undeclared indentifier '";
+				ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
+				ss << "' in call to waitfor";
+				throw SemanticError( ss.str() );
+			}
+
+			// Find all alternatives for all arguments in canonical form
+			std::list< AlternativeFinder > argAlternatives;
+			funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) );
+
+			// List all combinations of arguments
+			std::list< AltList > possibilities;
+			combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
+
+			AltList                func_candidates;
+			std::vector< AltList > args_candidates;
+
+			// For every possible function :
+			// 	try matching the arguments to the parameters
+			// 	not the other way around because we have more arguments than parameters
+			SemanticError errors;
+			for ( Alternative & func : funcFinder.get_alternatives() ) {
+				try {
+					PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
+					if( !pointer ) {
+						throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() );
+					}
+
+					FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
+					if( !function ) {
+						throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() );
+					}
+
+
+					{
+						auto param     = function->parameters.begin();
+						auto param_end = function->parameters.end();
+
+						if( !advance_to_mutex( param, param_end ) ) {
+							throw SemanticError("candidate function not viable: no mutex parameters\n", function);
+						}
+					}
+
+					Alternative newFunc( func );
+					// Strip reference from function
+					referenceToRvalueConversion( newFunc.expr );
+
+					// For all the set of arguments we have try to match it with the parameter of the current function alternative
+					for ( auto & argsList : possibilities ) {
+
+						try {
+							// Declare data structures need for resolution
+							OpenVarSet openVars;
+							AssertionSet resultNeed, resultHave;
+							TypeEnvironment resultEnv;
+
+							// Load type variables from arguemnts into one shared space
+							simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv );
+
+							// Make sure we don't widen any existing bindings
+							for ( auto & i : resultEnv ) {
+								i.allowWidening = false;
+							}
+
+							// Find any unbound type variables
+							resultEnv.extractOpenVars( openVars );
+
+							auto param     = function->parameters.begin();
+							auto param_end = function->parameters.end();
+
+							// For every arguments of its set, check if it matches one of the parameter
+							// The order is important
+							for( auto & arg : argsList ) {
+
+								// Ignore non-mutex arguments
+								if( !advance_to_mutex( param, param_end ) ) {
+									// We ran out of parameters but still have arguments
+									// this function doesn't match
+									throw SemanticError("candidate function not viable: too many mutex arguments\n", function);
+								}
+
+								// Check if the argument matches the parameter type in the current scope
+								if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
+									// Type doesn't match
+									stringstream ss;
+									ss << "candidate function not viable: no known convertion from '";
+									arg.expr->get_result()->print( ss );
+									ss << "' to '";
+									(*param)->get_type()->print( ss );
+									ss << "'\n";
+									throw SemanticError(ss.str(), function);
+								}
+
+								param++;
+							}
+
+							// All arguments match !
+
+							// Check if parameters are missing
+							if( advance_to_mutex( param, param_end ) ) {
+								// We ran out of arguments but still have parameters left
+								// this function doesn't match
+								throw SemanticError("candidate function not viable: too few mutex arguments\n", function);
+							}
+
+							// All parameters match !
+
+							// Finish the expressions to tie in the proper environments
+							finishExpr( newFunc.expr, resultEnv );
+							for( Alternative & alt : argsList ) {
+								finishExpr( alt.expr, resultEnv );
+							}
+
+							// This is a match store it and save it for later
+							func_candidates.push_back( newFunc );
+							args_candidates.push_back( argsList );
+
+						}
+						catch( SemanticError &e ) {
+							errors.append( e );
+						}
+					}
+				}
+				catch( SemanticError &e ) {
+					errors.append( e );
+				}
+			}
+
+			// Make sure we got the right number of arguments
+			if( func_candidates.empty() )    { SemanticError top( "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
+			if( args_candidates.empty() )    { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
+			if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
+			if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
+
+
+			// Swap the results from the alternative with the unresolved values.
+			// Alternatives will handle deletion on destruction
+			std::swap( clause.target.function, func_candidates.front().expr );
+			for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) {
+				std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr );
+			}
+
+			// Resolve the conditions as if it were an IfStmt
+			// Resolve the statments normally
+			resolveAsIf( clause.condition, this->indexer );
+			clause.statement->accept( *visitor );
+		}
+
+
+		if( stmt->timeout.statement ) {
+			// Resolve the timeout as an size_t for now
+			// Resolve the conditions as if it were an IfStmt
+			// Resolve the statments normally
+			resolveAsType( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer );
+			resolveAsIf  ( stmt->timeout.condition, this->indexer );
+			stmt->timeout.statement->accept( *visitor );
+		}
+
+		if( stmt->orelse.statement ) {
+			// Resolve the conditions as if it were an IfStmt
+			// Resolve the statments normally
+			resolveAsIf( stmt->orelse.condition, this->indexer );
+			stmt->orelse.statement->accept( *visitor );
+		}
+	}
+
 	template< typename T >
 	bool isCharType( T t ) {
