Big assertion capture refactoring.
- moved as much logic out of the macros as possible
- moved most logic into new ResultBuilder class, which wraps ExpressionResultBuilder (may take it over next), subsumes ResultAction and also takes place of ExpressionDecomposer.

This introduces many SRP violations - but all in the name of minimising macro logic!
diff --git a/include/catch.hpp b/include/catch.hpp
index 1df3eeb..7762981 100644
--- a/include/catch.hpp
+++ b/include/catch.hpp
@@ -63,7 +63,7 @@
 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "CATCH_REQUIRE_FALSE" )
 
-#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
+#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
 #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
 
@@ -73,7 +73,7 @@
 #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
 #define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
 
-#define CATCH_CHECK_THROWS( expr )  INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
+#define CATCH_CHECK_THROWS( expr )  INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
 #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
 
@@ -126,7 +126,7 @@
 #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" )
 
-#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
+#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
 #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
 
@@ -136,7 +136,7 @@
 #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
 #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
 
-#define CHECK_THROWS( expr )  INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
+#define CHECK_THROWS( expr )  INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
 #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
 
diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp
index a86bb2c..8a463dd 100644
--- a/include/internal/catch_capture.hpp
+++ b/include/internal/catch_capture.hpp
@@ -8,85 +8,38 @@
 #ifndef TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
 
-#include "catch_expression_decomposer.hpp"
-#include "catch_expressionresult_builder.h"
+#include "catch_result_builder.h"
 #include "catch_message.h"
 #include "catch_interfaces_capture.h"
 #include "catch_debugger.h"
-#include "catch_context.h"
 #include "catch_common.h"
 #include "catch_tostring.h"
-#include "catch_interfaces_registry_hub.h"
-#include "catch_interfaces_config.h"
+#include "catch_interfaces_runner.h"
 #include "internal/catch_compiler_capabilities.h"
 
-#include <ostream>
-
-namespace Catch {
-
-    inline IResultCapture& getResultCapture() {
-        if( IResultCapture* capture = getCurrentContext().getResultCapture() )
-            return *capture;
-        else
-            throw std::logic_error( "No result capture instance" );
-    }
-
-    template<typename MatcherT>
-    ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
-                                                                std::string const& matcherCallAsString ) {
-        std::string matcherAsString = matcher.toString();
-        if( matcherAsString == "{?}" )
-            matcherAsString = matcherCallAsString;
-        return ExpressionResultBuilder()
-            .setRhs( matcherAsString )
-            .setOp( "matches" );
-    }
-
-    template<typename MatcherT, typename ArgT>
-    ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
-                                                                ArgT const& arg,
-                                                                std::string const& matcherCallAsString ) {
-        return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
-            .setLhs( Catch::toString( arg ) )
-            .setResultType( matcher.match( arg ) );
-    }
-
-    template<typename MatcherT, typename ArgT>
-    ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
-                                                                ArgT* arg,
-                                                                std::string const& matcherCallAsString ) {
-        return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
-            .setLhs( Catch::toString( arg ) )
-            .setResultType( matcher.match( arg ) );
-    }
-
-struct TestFailureException{};
-
-} // end namespace Catch
-
 
 ///////////////////////////////////////////////////////////////////////////////
-#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \
-    if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, __assertionInfo )  ) { \
-        if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \
-        if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
-        if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \
-        Catch::isTrue( false && originalExpr ); \
-    }
+// In the event of a failure works out if the debugger needs to be invoked
+// and/or an exception thrown and takes appropriate action.
+// This needs to be done as a macro so the debugger will stop in the user
+// source code rather than in Catch library code
+#define INTERNAL_CATCH_REACT( resultBuilder ) \
+    if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
+    resultBuilder.react();
+
 
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
     do { \
-        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
         try { \
-            INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
-        } catch( Catch::TestFailureException& ) { \
-            throw; \
-        } catch( ... ) { \
-            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
-                Catch::ResultDisposition::Normal, expr ); \
+            ( __catchResult->*expr ).endExpression(); \
         } \
-    } while( Catch::isTrue( false ) )
+        catch( ... ) { \
+            __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
+        } \
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::alwaysFalse() && (expr) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
 
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
@@ -101,82 +54,90 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
     do { \
-        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
         try { \
             expr; \
-            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
+            __catchResult.captureResult( Catch::ResultWas::Ok ); \
         } \
         catch( ... ) { \
-            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \
+            __catchResult.useActiveException( resultDisposition ); \
         } \
-} while( Catch::isTrue( false ) )
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::alwaysFalse() )
 
 ///////////////////////////////////////////////////////////////////////////////
-#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
-    try { \
-        if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
-            expr; \
-            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
-        } \
-    } \
-    catch( Catch::TestFailureException& ) { \
-        throw; \
-    } \
-    catch( exceptionType ) { \
-        INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
-    }
-
-///////////////////////////////////////////////////////////////////////////////
-#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \
+#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \
     do { \
-        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
-        INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
-    } while( Catch::isTrue( false ) )
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+        try { \
+            if( __catchResult.allowThrows() ) \
+                expr; \
+            __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
+        } \
+        catch( ... ) { \
+            __catchResult.captureResult( Catch::ResultWas::Ok ); \
+        } \
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::alwaysFalse() )
 
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
     do { \
-        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
-        INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
-        catch( ... ) { \
-            INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
-                resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+        try { \
+            if( __catchResult.allowThrows() ) \
+                expr; \
+            __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
         } \
-    } while( Catch::isTrue( false ) )
+        catch( exceptionType ) { \
+            __catchResult.captureResult( Catch::ResultWas::Ok ); \
+        } \
+        catch( ... ) { \
+            __catchResult.useActiveException( resultDisposition ); \
+        } \
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::alwaysFalse() )
 
 
 ///////////////////////////////////////////////////////////////////////////////
 #ifdef CATCH_CONFIG_VARIADIC_MACROS
     #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
         do { \
-            Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
-            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << __VA_ARGS__ +::Catch::StreamEndStop(), resultDisposition, true ) \
-        } while( Catch::isTrue( false ) )
+            Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+            __catchResult.m_resultBuilder << __VA_ARGS__ + ::Catch::StreamEndStop(); \
+            __catchResult.captureResult( messageType ); \
+            INTERNAL_CATCH_REACT( __catchResult ) \
+        } while( Catch::alwaysFalse() )
 #else
     #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
         do { \
-            Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
-            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \
-        } while( Catch::isTrue( false ) )
+            Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+            __catchResult.m_resultBuilder << log + ::Catch::StreamEndStop(); \
+            __catchResult.captureResult( messageType ); \
+            INTERNAL_CATCH_REACT( __catchResult ) \
+        } while( Catch::alwaysFalse() )
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_INFO( log, macroName ) \
     Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
 
-
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
     do { \
-        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
+        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
         try { \
-            INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
-        } catch( Catch::TestFailureException& ) { \
-            throw; \
+            std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \
+            __catchResult.m_resultBuilder \
+                .setLhs( Catch::toString( arg ) ) \
+                .setRhs( matcherAsString == "{?}" ? #matcher : matcherAsString ) \
+                .setOp( "matches" ) \
+                .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \
+            __catchResult.captureExpression(); \
         } catch( ... ) { \
-            INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
-                resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
+            __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
         } \
-    } while( Catch::isTrue( false ) )
+        INTERNAL_CATCH_REACT( __catchResult ) \
+    } while( Catch::alwaysFalse() )
 
 #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h
index 7fb88ae..967b7fc 100644
--- a/include/internal/catch_common.h
+++ b/include/internal/catch_common.h
@@ -94,6 +94,8 @@
 
     // This is just here to avoid compiler warnings with macro constants and boolean literals
     inline bool isTrue( bool value ){ return value; }
+    inline bool alwaysTrue() { return true; }
+    inline bool alwaysFalse() { return false; }
 
     void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
 
diff --git a/include/internal/catch_common.hpp b/include/internal/catch_common.hpp
index 89ffeab..6147aa5 100644
--- a/include/internal/catch_common.hpp
+++ b/include/internal/catch_common.hpp
@@ -77,7 +77,7 @@
     void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
         std::ostringstream oss;
         oss << locationInfo << ": Internal Catch error: '" << message << "'";
-        if( isTrue( true ))
+        if( alwaysTrue() )
             throw std::logic_error( oss.str() );
     }
 }
diff --git a/include/internal/catch_debugger.h b/include/internal/catch_debugger.h
index 1ac53cd..0dd36aa 100644
--- a/include/internal/catch_debugger.h
+++ b/include/internal/catch_debugger.h
@@ -43,7 +43,7 @@
 #endif
 
 #ifndef CATCH_BREAK_INTO_DEBUGGER
-#define CATCH_BREAK_INTO_DEBUGGER() Catch::isTrue( true );
+#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
 #endif
 
 #endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
diff --git a/include/internal/catch_exception_translator_registry.hpp b/include/internal/catch_exception_translator_registry.hpp
index ffa14b1..a1cc705 100644
--- a/include/internal/catch_exception_translator_registry.hpp
+++ b/include/internal/catch_exception_translator_registry.hpp
@@ -41,6 +41,9 @@
                 throw;
 #endif
             }
+            catch( TestFailureException& ) {
+                throw;
+            }
             catch( std::exception& ex ) {
                 return ex.what();
             }
diff --git a/include/internal/catch_expression_decomposer.hpp b/include/internal/catch_expression_decomposer.hpp
deleted file mode 100644
index 9d8fd35..0000000
--- a/include/internal/catch_expression_decomposer.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  Created by Phil on 11/5/2012.
- *  Copyright 2012 Two Blue Cubes Ltd. All rights reserved.
- *
- *  Distributed under the Boost Software License, Version 1.0. (See accompanying
- *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- */
-#ifndef TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
-#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
-
-#include "catch_expression_lhs.hpp"
-
-namespace Catch {
-
-// Captures the LHS of the expression and wraps it in an Expression Lhs object
-class ExpressionDecomposer {
-public:
-
-    template<typename T>
-    ExpressionLhs<T const&> operator->* ( T const& operand ) {
-        return ExpressionLhs<T const&>( operand );
-    }
-
-    ExpressionLhs<bool> operator->* ( bool value ) {
-        return ExpressionLhs<bool>( value );
-    }
-};
-
-} // end namespace Catch
-
-#endif // TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp
index e3436ed..c89cb55 100644
--- a/include/internal/catch_expression_lhs.hpp
+++ b/include/internal/catch_expression_lhs.hpp
@@ -8,12 +8,19 @@
 #ifndef TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
 
+#include "catch_result_builder.h"
 #include "catch_expressionresult_builder.h"
 #include "catch_evaluate.hpp"
 #include "catch_tostring.h"
 
+#include <assert.h>
+
 namespace Catch {
 
+struct ResultBuilder;
+
+ExpressionResultBuilder& getResultBuilder( ResultBuilder* rb );
+
 // Wraps the LHS of an expression and captures the operator and RHS (if any) -
 // wrapping them all in an ExpressionResultBuilder object
 template<typename T>
@@ -24,7 +31,7 @@
 #  endif
 
 public:
-    ExpressionLhs( T lhs ) : m_lhs( lhs ) {}
+    ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( &rb ), m_lhs( lhs ) {}
 #  ifdef CATCH_CPP11_OR_GREATER
     ExpressionLhs( ExpressionLhs const& ) = default;
     ExpressionLhs( ExpressionLhs && )     = default;
@@ -68,12 +75,13 @@
         return captureExpression<Internal::IsNotEqualTo>( rhs );
     }
 
-    ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) {
+    void endExpression() {
+        assert( m_rb );
         bool value = m_lhs ? true : false;
-        return m_result
+        getResultBuilder( m_rb )
             .setLhs( Catch::toString( value ) )
             .setResultType( value )
-            .endExpression( resultDisposition );
+            .endExpression();
     }
 
     // Only simple binary expressions are allowed on the LHS.
@@ -88,7 +96,8 @@
 private:
     template<Internal::Operator Op, typename RhsT>
     ExpressionResultBuilder& captureExpression( RhsT const& rhs ) {
-        return m_result
+        assert( m_rb );
+        return getResultBuilder( m_rb )
             .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
             .setLhs( Catch::toString( m_lhs ) )
             .setRhs( Catch::toString( rhs ) )
@@ -96,7 +105,7 @@
     }
 
 private:
-    ExpressionResultBuilder m_result;
+    ResultBuilder* m_rb;
     T m_lhs;
 };
 
diff --git a/include/internal/catch_expressionresult_builder.h b/include/internal/catch_expressionresult_builder.h
index 8d4ec14..a2010b8 100644
--- a/include/internal/catch_expressionresult_builder.h
+++ b/include/internal/catch_expressionresult_builder.h
@@ -17,15 +17,16 @@
 namespace Catch {
 
 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
+struct ResultBuilder;
 
 // Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as
 // the result of evaluating it. This is used to build an AssertionResult object
 class ExpressionResultBuilder {
 public:
 
-    ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown );
+    ExpressionResultBuilder( ResultBuilder* rb, ResultWas::OfType resultType = ResultWas::Unknown );
     ExpressionResultBuilder( ExpressionResultBuilder const& other );
-    ExpressionResultBuilder& operator=(ExpressionResultBuilder const& other );
+    ExpressionResultBuilder& operator=( ExpressionResultBuilder const& other );
 
     ExpressionResultBuilder& setResultType( ResultWas::OfType result );
     ExpressionResultBuilder& setResultType( bool result );
@@ -33,7 +34,7 @@
     ExpressionResultBuilder& setRhs( std::string const& rhs );
     ExpressionResultBuilder& setOp( std::string const& op );
 
-    ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition );
+    void endExpression();
 
     template<typename T>
     ExpressionResultBuilder& operator << ( T const& value ) {
@@ -49,6 +50,7 @@
     template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
 
 private:
+    ResultBuilder* m_rb;
     AssertionResultData m_data;
     struct ExprComponents {
         ExprComponents() : shouldNegate( false ) {}
diff --git a/include/internal/catch_expressionresult_builder.hpp b/include/internal/catch_expressionresult_builder.hpp
index 2a451ea..c2854e6 100644
--- a/include/internal/catch_expressionresult_builder.hpp
+++ b/include/internal/catch_expressionresult_builder.hpp
@@ -9,21 +9,25 @@
 #define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED
 
 #include "catch_expressionresult_builder.h"
+#include "catch_result_builder.h"
 
 #include <assert.h>
 
 namespace Catch {
 
-    ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) {
+    ExpressionResultBuilder::ExpressionResultBuilder( ResultBuilder* rb, ResultWas::OfType resultType )
+    : m_rb( rb ) {
         m_data.resultType = resultType;
     }
     ExpressionResultBuilder::ExpressionResultBuilder( ExpressionResultBuilder const& other )
-    :   m_data( other.m_data ),
+    :   m_rb( other.m_rb ),
+        m_data( other.m_data ),
         m_exprComponents( other.m_exprComponents )
     {
         m_stream << other.m_stream.str();
     }
     ExpressionResultBuilder& ExpressionResultBuilder::operator=(ExpressionResultBuilder const& other ) {
+        m_rb = other.m_rb;
         m_data = other.m_data;
         m_exprComponents = other.m_exprComponents;
         m_stream.str("");
@@ -38,9 +42,9 @@
         m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
         return *this;
     }
-    ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) {
-        m_exprComponents.shouldNegate = shouldNegate( resultDisposition );
-        return *this;
+    void ExpressionResultBuilder::endExpression() {
+        m_exprComponents.shouldNegate = shouldNegate( m_rb->m_assertionInfo.resultDisposition );
+        m_rb->captureExpression();
     }
     ExpressionResultBuilder& ExpressionResultBuilder::setLhs( std::string const& lhs ) {
         m_exprComponents.lhs = lhs;
@@ -54,6 +58,7 @@
         m_exprComponents.op = op;
         return *this;
     }
+
     AssertionResult ExpressionResultBuilder::buildResult( AssertionInfo const& info ) const
     {
         assert( m_data.resultType != ResultWas::Unknown );
diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp
index f352f00..f8ac4ef 100644
--- a/include/internal/catch_impl.hpp
+++ b/include/internal/catch_impl.hpp
@@ -34,6 +34,7 @@
 #include "catch_section.hpp"
 #include "catch_debugger.hpp"
 #include "catch_tostring.hpp"
+#include "catch_result_builder.hpp"
 
 #include "../reporters/catch_reporter_xml.hpp"
 #include "../reporters/catch_reporter_junit.hpp"
diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h
index de779e0..d6b244e 100644
--- a/include/internal/catch_interfaces_capture.h
+++ b/include/internal/catch_interfaces_capture.h
@@ -34,13 +34,11 @@
         virtual void pushScopedMessage( MessageInfo const& message ) = 0;
         virtual void popScopedMessage( MessageInfo const& message ) = 0;
 
-        virtual bool shouldDebugBreak() const = 0;
-
-        virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) = 0;
-
         virtual std::string getCurrentTestName() const = 0;
         virtual const AssertionResult* getLastResult() const = 0;
     };
+
+    IResultCapture& getResultCapture();
 }
 
 #endif // TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
diff --git a/include/internal/catch_interfaces_runner.h b/include/internal/catch_interfaces_runner.h
index 6438f20..25decfb 100644
--- a/include/internal/catch_interfaces_runner.h
+++ b/include/internal/catch_interfaces_runner.h
@@ -13,6 +13,7 @@
 
     struct IRunner {
         virtual ~IRunner();
+        virtual bool aborting() const = 0;
     };
 }
 
diff --git a/include/internal/catch_legacy_reporter_adapter.hpp b/include/internal/catch_legacy_reporter_adapter.hpp
index 0911afa..bc286f1 100644
--- a/include/internal/catch_legacy_reporter_adapter.hpp
+++ b/include/internal/catch_legacy_reporter_adapter.hpp
@@ -46,7 +46,7 @@
                     it != itEnd;
                     ++it ) {
                 if( it->type == ResultWas::Info ) {
-                    ExpressionResultBuilder expressionBuilder( it->type );
+                    ExpressionResultBuilder expressionBuilder( NULL, it->type );
                         expressionBuilder << it->message;
                     AssertionInfo info( it->macroName, it->lineInfo, "", ResultDisposition::Normal );
                     AssertionResult result = expressionBuilder.buildResult( info );
diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h
new file mode 100644
index 0000000..7db8b30
--- /dev/null
+++ b/include/internal/catch_result_builder.h
@@ -0,0 +1,49 @@
+/*
+ *  Created by Phil on 28/5/2014.
+ *  Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
+#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
+
+#include "catch_expression_lhs.hpp"
+#include "catch_expressionresult_builder.h"
+#include "catch_common.h"
+
+namespace Catch {
+
+    struct TestFailureException{};
+
+    struct ResultBuilder {
+        ResultBuilder(  char const* macroName,
+                        SourceLineInfo const& lineInfo,
+                        char const* capturedExpression,
+                        ResultDisposition::Flags resultDisposition );
+
+        template<typename T>
+        ExpressionLhs<T const&> operator->* ( T const& operand ) {
+            return ExpressionLhs<T const&>( *this, operand );
+        }
+
+        ExpressionLhs<bool> operator->* ( bool value ) {
+            return ExpressionLhs<bool>( *this, value );
+        }
+
+        void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
+        void captureResult( ResultWas::OfType resultType );
+        void captureExpression();
+        void react();
+        bool shouldDebugBreak() const;
+        bool allowThrows() const;
+
+        AssertionInfo m_assertionInfo;
+        ExpressionResultBuilder m_resultBuilder;
+        bool m_shouldDebugBreak;
+        bool m_shouldThrow;
+    };
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp
new file mode 100644
index 0000000..aead597
--- /dev/null
+++ b/include/internal/catch_result_builder.hpp
@@ -0,0 +1,69 @@
+/*
+ *  Created by Phil on 28/5/2014.
+ *  Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
+
+#include "catch_result_builder.h"
+#include "catch_expressionresult_builder.h"
+#include "catch_context.h"
+#include "catch_common.h"
+#include "catch_interfaces_config.h"
+#include "catch_interfaces_runner.h"
+#include "catch_interfaces_capture.h"
+#include "catch_interfaces_registry_hub.h"
+
+
+namespace Catch {
+
+    ExpressionResultBuilder& getResultBuilder( ResultBuilder* rb ) {
+        return rb->m_resultBuilder;
+    }
+
+    ResultBuilder::ResultBuilder(   char const* macroName,
+                                    SourceLineInfo const& lineInfo,
+                                    char const* capturedExpression,
+                                    ResultDisposition::Flags resultDisposition )
+        :   m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ),
+            m_resultBuilder( this ),
+            m_shouldDebugBreak( false ),
+            m_shouldThrow( false )
+        {}
+
+    void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
+        m_assertionInfo.resultDisposition = resultDisposition;
+        m_resultBuilder << Catch::translateActiveException();
+        captureResult( ResultWas::ThrewException );
+    }
+
+    void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
+        m_resultBuilder.setResultType( resultType );
+        captureExpression();
+    }
+
+    void ResultBuilder::captureExpression() {
+        AssertionResult result = m_resultBuilder.buildResult( m_assertionInfo );
+        getResultCapture().assertionEnded( result );
+
+        if( !result.isOk() ) {
+            if( getCurrentContext().getConfig()->shouldDebugBreak() )
+                m_shouldDebugBreak = true;
+            if( getCurrentContext().getRunner()->aborting() || m_assertionInfo.resultDisposition == ResultDisposition::Normal )
+                m_shouldThrow = true;
+        }
+    }
+    void ResultBuilder::react() {
+        if( m_shouldThrow )
+            throw Catch::TestFailureException();
+    }
+
+    bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
+    bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
diff --git a/include/internal/catch_result_type.h b/include/internal/catch_result_type.h
index 9aed2bd..751a713 100644
--- a/include/internal/catch_result_type.h
+++ b/include/internal/catch_result_type.h
@@ -36,13 +36,6 @@
         return flags == ResultWas::Info;
     }
 
-    // ResultAction::Value enum
-    struct ResultAction { enum Value {
-        None,
-        Failed = 1, // Failure - but no debug break if Debug bit not set
-        Debug = 2,  // If this bit is set, invoke the debugger
-        Abort = 4   // Test run should abort
-    }; };
 
     // ResultDisposition::Flags enum
     struct ResultDisposition { enum Flags {
@@ -60,7 +53,7 @@
     inline bool shouldContinueOnFailure( int flags )    { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
     inline bool shouldNegate( int flags )               { return ( flags & ResultDisposition::NegateResult ) != 0; }
     inline bool shouldSuppressFailure( int flags )      { return ( flags & ResultDisposition::SuppressFail ) != 0; }
-
+    
 } // end namespace Catch
 
 #endif // TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp
index b4f53d5..06cca6f 100644
--- a/include/internal/catch_runner_impl.hpp
+++ b/include/internal/catch_runner_impl.hpp
@@ -19,6 +19,7 @@
 #include "catch_test_spec.hpp"
 #include "catch_test_case_tracker.hpp"
 #include "catch_timer.h"
+#include "catch_result_builder.h"
 
 #include <set>
 #include <string>
@@ -129,10 +130,6 @@
 
     private: // IResultCapture
 
-        virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) {
-            m_lastAssertionInfo = assertionInfo;
-            return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) );
-        }
 
         virtual void assertionEnded( AssertionResult const& result ) {
             if( result.getResultType() == ResultWas::Ok ) {
@@ -147,6 +144,7 @@
 
             // Reset working state
             m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
+            m_lastResult = result;
         }
 
         virtual bool sectionStarted (
@@ -201,10 +199,6 @@
             m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
         }
 
-        virtual bool shouldDebugBreak() const {
-            return m_config->shouldDebugBreak();
-        }
-
         virtual std::string getCurrentTestName() const {
             return m_activeTestCase
                 ? m_activeTestCase->getTestCaseInfo().name
@@ -223,22 +217,6 @@
 
     private:
 
-        ResultAction::Value actOnCurrentResult( AssertionResult const& result ) {
-            m_lastResult = result;
-            assertionEnded( m_lastResult );
-
-            ResultAction::Value action = ResultAction::None;
-
-            if( !m_lastResult.isOk() ) {
-                action = ResultAction::Failed;
-                if( shouldDebugBreak() )
-                    action = (ResultAction::Value)( action | ResultAction::Debug );
-                if( aborting() )
-                    action = (ResultAction::Value)( action | ResultAction::Abort );
-            }
-            return action;
-        }
-
         void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
             TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
             SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo );
@@ -265,9 +243,11 @@
                 // This just means the test was aborted due to failure
             }
             catch(...) {
-                ExpressionResultBuilder exResult( ResultWas::ThrewException );
-                exResult << translateActiveException();
-                actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo )  );
+                ResultBuilder exResult( m_lastAssertionInfo.macroName.c_str(),
+                                        m_lastAssertionInfo.lineInfo,
+                                        m_lastAssertionInfo.capturedExpression.c_str(),
+                                        m_lastAssertionInfo.resultDisposition );
+                exResult.useActiveException();
             }
             // If sections ended prematurely due to an exception we stored their
             // infos here so we can tear them down outside the unwind process.
@@ -314,6 +294,13 @@
         std::vector<UnfinishedSections> m_unfinishedSections;
     };
 
+    IResultCapture& getResultCapture() {
+        if( IResultCapture* capture = getCurrentContext().getResultCapture() )
+            return *capture;
+        else
+            throw std::logic_error( "No result capture instance" );
+    }
+
 } // end namespace Catch
 
 #endif // TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt
index 3a56e6a..c6a11ee 100644
--- a/projects/SelfTest/Baselines/console.sw.approved.txt
+++ b/projects/SelfTest/Baselines/console.sw.approved.txt
@@ -5683,7 +5683,7 @@
 
 TrickyTests.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::isTrue( true ) )
+  REQUIRE( Catch::alwaysTrue() )
 with expansion:
   true
 
@@ -5696,7 +5696,7 @@
 
 TrickyTests.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::isTrue( true ) )
+  REQUIRE( Catch::alwaysTrue() )
 with expansion:
   true
 
@@ -5710,7 +5710,7 @@
 
 TrickyTests.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::isTrue( true ) )
+  REQUIRE( Catch::alwaysTrue() )
 with expansion:
   true
 
@@ -5722,7 +5722,7 @@
 
 TrickyTests.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::isTrue( true ) )
+  REQUIRE( Catch::alwaysTrue() )
 with expansion:
   true
 
@@ -5735,7 +5735,7 @@
 
 TrickyTests.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::isTrue( true ) )
+  REQUIRE( Catch::alwaysTrue() )
 with expansion:
   true
 
@@ -5749,7 +5749,7 @@
 
 TrickyTests.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::isTrue( true ) )
+  REQUIRE( Catch::alwaysTrue() )
 with expansion:
   true
 
diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt
index f6249b1..5e4e2c4 100644
--- a/projects/SelfTest/Baselines/xml.sw.approved.txt
+++ b/projects/SelfTest/Baselines/xml.sw.approved.txt
@@ -5849,7 +5849,7 @@
     <TestCase name="Assertions then sections">
       <Expression success="true" filename="/Users/philnash/Dev/OSS/Catch/projects/SelfTest/TrickyTests.cpp" >
         <Original>
-          Catch::isTrue( true )
+          Catch::alwaysTrue()
         </Original>
         <Expanded>
           true
@@ -5858,7 +5858,7 @@
       <Section name="A section">
         <Expression success="true" filename="/Users/philnash/Dev/OSS/Catch/projects/SelfTest/TrickyTests.cpp" >
           <Original>
-            Catch::isTrue( true )
+            Catch::alwaysTrue()
           </Original>
           <Expanded>
             true
@@ -5867,7 +5867,7 @@
         <Section name="Another section">
           <Expression success="true" filename="/Users/philnash/Dev/OSS/Catch/projects/SelfTest/TrickyTests.cpp" >
             <Original>
-              Catch::isTrue( true )
+              Catch::alwaysTrue()
             </Original>
             <Expanded>
               true
@@ -5879,7 +5879,7 @@
       </Section>
       <Expression success="true" filename="/Users/philnash/Dev/OSS/Catch/projects/SelfTest/TrickyTests.cpp" >
         <Original>
-          Catch::isTrue( true )
+          Catch::alwaysTrue()
         </Original>
         <Expanded>
           true
@@ -5888,7 +5888,7 @@
       <Section name="A section">
         <Expression success="true" filename="/Users/philnash/Dev/OSS/Catch/projects/SelfTest/TrickyTests.cpp" >
           <Original>
-            Catch::isTrue( true )
+            Catch::alwaysTrue()
           </Original>
           <Expanded>
             true
@@ -5897,7 +5897,7 @@
         <Section name="Another other section">
           <Expression success="true" filename="/Users/philnash/Dev/OSS/Catch/projects/SelfTest/TrickyTests.cpp" >
             <Original>
-              Catch::isTrue( true )
+              Catch::alwaysTrue()
             </Original>
             <Expanded>
               true
diff --git a/projects/SelfTest/CmdLineTests.cpp b/projects/SelfTest/CmdLineTests.cpp
index a667ce3..46aecfd 100644
--- a/projects/SelfTest/CmdLineTests.cpp
+++ b/projects/SelfTest/CmdLineTests.cpp
@@ -22,42 +22,42 @@
     Catch::TestCase tcC = fakeTestCase( "longer name with spaces", "[two][three][.][x]" );
     Catch::TestCase tcD = fakeTestCase( "zlonger name with spacesz", "" );
 
-    SECTION( "Empty test spec should have no filters" ) {
+    SECTION( "Empty test spec should have no filters", "" ) {
         TestSpec spec;
         CHECK( spec.hasFilters() == false );
         CHECK( spec.matches( tcA ) == false );
         CHECK( spec.matches( tcB ) == false );
     }
 
-    SECTION( "Test spec from empty string should have no filters" ) {
+    SECTION( "Test spec from empty string should have no filters", "" ) {
         TestSpec spec = parseTestSpec( "" );
         CHECK( spec.hasFilters() == false );
         CHECK( spec.matches(tcA ) == false );
         CHECK( spec.matches( tcB ) == false );
     }
 
-    SECTION( "Test spec from just a comma should have no filters" ) {
+    SECTION( "Test spec from just a comma should have no filters", "" ) {
         TestSpec spec = parseTestSpec( "," );
         CHECK( spec.hasFilters() == false );
         CHECK( spec.matches( tcA ) == false );
         CHECK( spec.matches( tcB ) == false );
     }
 
-    SECTION( "Test spec from name should have one filter" ) {
+    SECTION( "Test spec from name should have one filter", "" ) {
         TestSpec spec = parseTestSpec( "b" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
         CHECK( spec.matches( tcB ) == true );
     }
 
-    SECTION( "Test spec from quoted name should have one filter" ) {
+    SECTION( "Test spec from quoted name should have one filter", "" ) {
         TestSpec spec = parseTestSpec( "\"b\"" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
         CHECK( spec.matches( tcB ) == true );
     }
 
-    SECTION( "Test spec from name should have one filter" ) {
+    SECTION( "Test spec from name should have one filter", "" ) {
         TestSpec spec = parseTestSpec( "b" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
@@ -65,7 +65,7 @@
         CHECK( spec.matches( tcC ) == false );
     }
 
-    SECTION( "Wildcard at the start" ) {
+    SECTION( "Wildcard at the start", "" ) {
         TestSpec spec = parseTestSpec( "*spaces" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
@@ -74,7 +74,7 @@
         CHECK( spec.matches( tcD ) == false );
         CHECK( parseTestSpec( "*a" ).matches( tcA ) == true );
     }
-    SECTION( "Wildcard at the end" ) {
+    SECTION( "Wildcard at the end", "" ) {
         TestSpec spec = parseTestSpec( "long*" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
@@ -83,7 +83,7 @@
         CHECK( spec.matches( tcD ) == false );
         CHECK( parseTestSpec( "a*" ).matches( tcA ) == true );
     }
-    SECTION( "Wildcard at both ends" ) {
+    SECTION( "Wildcard at both ends", "" ) {
         TestSpec spec = parseTestSpec( "*name*" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
@@ -92,25 +92,25 @@
         CHECK( spec.matches( tcD ) == true );
         CHECK( parseTestSpec( "*a*" ).matches( tcA ) == true );
     }
-    SECTION( "Redundant wildcard at the start" ) {
+    SECTION( "Redundant wildcard at the start", "" ) {
         TestSpec spec = parseTestSpec( "*a" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == true );
         CHECK( spec.matches( tcB ) == false );
     }
-    SECTION( "Redundant wildcard at the end" ) {
+    SECTION( "Redundant wildcard at the end", "" ) {
         TestSpec spec = parseTestSpec( "a*" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == true );
         CHECK( spec.matches( tcB ) == false );
     }
-    SECTION( "Redundant wildcard at both ends" ) {
+    SECTION( "Redundant wildcard at both ends", "" ) {
         TestSpec spec = parseTestSpec( "*a*" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == true );
         CHECK( spec.matches( tcB ) == false );
     }
-    SECTION( "Wildcard at both ends, redundant at start" ) {
+    SECTION( "Wildcard at both ends, redundant at start", "" ) {
         TestSpec spec = parseTestSpec( "*longer*" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
@@ -118,7 +118,7 @@
         CHECK( spec.matches( tcC ) == true );
         CHECK( spec.matches( tcD ) == true );
     }
-    SECTION( "Just wildcard" ) {
+    SECTION( "Just wildcard", "" ) {
         TestSpec spec = parseTestSpec( "*" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == true );
@@ -127,35 +127,35 @@
         CHECK( spec.matches( tcD ) == true );
     }
 
-    SECTION( "Single tag" ) {
+    SECTION( "Single tag", "" ) {
         TestSpec spec = parseTestSpec( "[one]" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
         CHECK( spec.matches( tcB ) == true );
         CHECK( spec.matches( tcC ) == false );
     }
-    SECTION( "Single tag, two matches" ) {
+    SECTION( "Single tag, two matches", "" ) {
         TestSpec spec = parseTestSpec( "[x]" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
         CHECK( spec.matches( tcB ) == true );
         CHECK( spec.matches( tcC ) == true );
     }
-    SECTION( "Two tags" ) {
+    SECTION( "Two tags", "" ) {
         TestSpec spec = parseTestSpec( "[two][x]" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
         CHECK( spec.matches( tcB ) == false );
         CHECK( spec.matches( tcC ) == true );
     }
-    SECTION( "Two tags, spare separated" ) {
+    SECTION( "Two tags, spare separated", "" ) {
         TestSpec spec = parseTestSpec( "[two] [x]" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
         CHECK( spec.matches( tcB ) == false );
         CHECK( spec.matches( tcC ) == true );
     }
-    SECTION( "Wildcarded name and tag" ) {
+    SECTION( "Wildcarded name and tag", "" ) {
         TestSpec spec = parseTestSpec( "*name*[x]" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
@@ -163,21 +163,21 @@
         CHECK( spec.matches( tcC ) == true );
         CHECK( spec.matches( tcD ) == false );
     }
-    SECTION( "Single tag exclusion" ) {
+    SECTION( "Single tag exclusion", "" ) {
         TestSpec spec = parseTestSpec( "~[one]" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == true );
         CHECK( spec.matches( tcB ) == false );
         CHECK( spec.matches( tcC ) == true );
     }
-    SECTION( "One tag exclusion and one tag inclusion" ) {
+    SECTION( "One tag exclusion and one tag inclusion", "" ) {
         TestSpec spec = parseTestSpec( "~[two][x]" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
         CHECK( spec.matches( tcB ) == true );
         CHECK( spec.matches( tcC ) == false );
     }
-    SECTION( "One tag exclusion and one wldcarded name inclusion" ) {
+    SECTION( "One tag exclusion and one wldcarded name inclusion", "" ) {
         TestSpec spec = parseTestSpec( "~[two]*name*" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
@@ -185,7 +185,7 @@
         CHECK( spec.matches( tcC ) == false );
         CHECK( spec.matches( tcD ) == true );
     }
-    SECTION( "One tag exclusion, using exclude:, and one wldcarded name inclusion" ) {
+    SECTION( "One tag exclusion, using exclude:, and one wldcarded name inclusion", "" ) {
         TestSpec spec = parseTestSpec( "exclude:[two]*name*" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
@@ -193,7 +193,7 @@
         CHECK( spec.matches( tcC ) == false );
         CHECK( spec.matches( tcD ) == true );
     }
-    SECTION( "name exclusion" ) {
+    SECTION( "name exclusion", "" ) {
         TestSpec spec = parseTestSpec( "~b" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == true );
@@ -201,7 +201,7 @@
         CHECK( spec.matches( tcC ) == true );
         CHECK( spec.matches( tcD ) == true );
     }
-    SECTION( "wildcarded name exclusion" ) {
+    SECTION( "wildcarded name exclusion", "" ) {
         TestSpec spec = parseTestSpec( "~*name*" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == true );
@@ -209,7 +209,7 @@
         CHECK( spec.matches( tcC ) == false );
         CHECK( spec.matches( tcD ) == false );
     }
-    SECTION( "wildcarded name exclusion with tag inclusion" ) {
+    SECTION( "wildcarded name exclusion with tag inclusion", "" ) {
         TestSpec spec = parseTestSpec( "~*name*,[three]" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == true );
@@ -217,7 +217,7 @@
         CHECK( spec.matches( tcC ) == true );
         CHECK( spec.matches( tcD ) == false );
     }
-    SECTION( "wildcarded name exclusion, using exclude:, with tag inclusion" ) {
+    SECTION( "wildcarded name exclusion, using exclude:, with tag inclusion", "" ) {
         TestSpec spec = parseTestSpec( "exclude:*name*,[three]" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == true );
@@ -225,7 +225,7 @@
         CHECK( spec.matches( tcC ) == true );
         CHECK( spec.matches( tcD ) == false );
     }
-    SECTION( "two wildcarded names" ) {
+    SECTION( "two wildcarded names", "" ) {
         TestSpec spec = parseTestSpec( "\"longer*\"\"*spaces\"" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
@@ -233,7 +233,7 @@
         CHECK( spec.matches( tcC ) == true );
         CHECK( spec.matches( tcD ) == false );
     }
-    SECTION( "empty tag" ) {
+    SECTION( "empty tag", "" ) {
         TestSpec spec = parseTestSpec( "[]" );
         CHECK( spec.hasFilters() == false );
         CHECK( spec.matches( tcA ) == false );
@@ -241,7 +241,7 @@
         CHECK( spec.matches( tcC ) == false );
         CHECK( spec.matches( tcD ) == false );
     }
-    SECTION( "empty quoted name" ) {
+    SECTION( "empty quoted name", "" ) {
         TestSpec spec = parseTestSpec( "\"\"" );
         CHECK( spec.hasFilters() == false );
         CHECK( spec.matches( tcA ) == false );
@@ -249,7 +249,7 @@
         CHECK( spec.matches( tcC ) == false );
         CHECK( spec.matches( tcD ) == false );
     }
-    SECTION( "quoted string followed by tag exclusion" ) {
+    SECTION( "quoted string followed by tag exclusion", "" ) {
         TestSpec spec = parseTestSpec( "\"*name*\"~[.]" );
         CHECK( spec.hasFilters() == true );
         CHECK( spec.matches( tcA ) == false );
diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp
index 9139b5c..7de1d17 100644
--- a/projects/SelfTest/ExceptionTests.cpp
+++ b/projects/SelfTest/ExceptionTests.cpp
@@ -15,7 +15,7 @@
 {
     inline int thisThrows()
     {
-		if( Catch::isTrue( true ) )
+		if( Catch::alwaysTrue() )
 		    throw std::domain_error( "expected exception" );
 		return 1;
     }
@@ -42,14 +42,14 @@
 
 TEST_CASE( "When unchecked exceptions are thrown directly they are always failures", "[.][failing]" )
 {
-	if( Catch::isTrue( true ) )
+	if( Catch::alwaysTrue() )
 	    throw std::domain_error( "unexpected exception" );
 }
 
 TEST_CASE( "An unchecked exception reports the line of the last assertion", "[.][failing]" )
 {
     CHECK( 1 == 1 );
-	if( Catch::isTrue( true ) )
+	if( Catch::alwaysTrue() )
 	    throw std::domain_error( "unexpected exception" );
 }
 
@@ -57,7 +57,7 @@
 {
     SECTION( "section name", "" )
     {
-		if( Catch::isTrue( true ) )
+		if( Catch::alwaysTrue() )
 			throw std::domain_error( "unexpected exception" );
     }
 }
@@ -118,12 +118,12 @@
 
 TEST_CASE("Unexpected custom exceptions can be translated", "[.][failing]" )
 {
-	if( Catch::isTrue( true ) )
+	if( Catch::alwaysTrue() )
 	    throw CustomException( "custom exception" );
 }
 
 inline void throwCustom() {
-	if( Catch::isTrue( true ) )
+	if( Catch::alwaysTrue() )
 		throw CustomException( "custom exception - not std" );
 }
 
@@ -140,7 +140,7 @@
 
 TEST_CASE( "Unexpected exceptions can be translated", "[.][failing]"  )
 {
-	if( Catch::isTrue( true ) )
+	if( Catch::alwaysTrue() )
 	    throw double( 3.14 );
 }
 
diff --git a/projects/SelfTest/MessageTests.cpp b/projects/SelfTest/MessageTests.cpp
index b6da5fe..69ef03d 100644
--- a/projects/SelfTest/MessageTests.cpp
+++ b/projects/SelfTest/MessageTests.cpp
@@ -7,6 +7,7 @@
  */
 
 #include "catch.hpp"
+#include <iostream>
 
 #ifdef __clang__
 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
diff --git a/projects/SelfTest/SectionTrackerTests.cpp b/projects/SelfTest/SectionTrackerTests.cpp
index df0f8ab..03d856d 100644
--- a/projects/SelfTest/SectionTrackerTests.cpp
+++ b/projects/SelfTest/SectionTrackerTests.cpp
@@ -14,7 +14,7 @@
 
 #include "catch.hpp"
 
-TEST_CASE( "section tracking" ) {
+TEST_CASE( "section tracking", "" ) {
 
     using namespace Catch;
     TestCaseTracker testCaseTracker( "test case" );
@@ -24,7 +24,7 @@
 
     CHECK_FALSE( testCaseTracker.isCompleted() );
 
-    SECTION( "test case with no sections" ) {
+    SECTION( "test case with no sections", "" ) {
 
         {
             TestCaseTracker::Guard guard( testCaseTracker );
@@ -33,7 +33,7 @@
         CHECK( testCaseTracker.isCompleted() );
     }
 
-    SECTION( "test case with one section" ) {
+    SECTION( "test case with one section", "" ) {
 
         {
             TestCaseTracker::Guard guard( testCaseTracker );
@@ -58,7 +58,7 @@
         }
     }
 
-    SECTION( "test case with two consecutive sections" ) {
+    SECTION( "test case with two consecutive sections", "" ) {
 
         // Enter test case
         {
@@ -93,7 +93,7 @@
         CHECK( testCaseTracker.isCompleted() );        
     }
 
-    SECTION( "test case with one section within another" ) {
+    SECTION( "test case with one section within another", "" ) {
 
         // Enter test case again
         {
diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp
index 1fa7e36..61c2e03 100644
--- a/projects/SelfTest/TrickyTests.cpp
+++ b/projects/SelfTest/TrickyTests.cpp
@@ -318,19 +318,19 @@
     // This was causing a failure due to the way the console reporter was handling
     // the current section
     
-    REQUIRE( Catch::isTrue( true ) );
+    REQUIRE( Catch::alwaysTrue() );
     
     SECTION( "A section", "" )
     {
-        REQUIRE( Catch::isTrue( true ) );
+        REQUIRE( Catch::alwaysTrue() );
         
         SECTION( "Another section", "" )
         {
-            REQUIRE( Catch::isTrue( true ) );
+            REQUIRE( Catch::alwaysTrue() );
         }
         SECTION( "Another other section", "" )
         {
-            REQUIRE( Catch::isTrue( true ) );
+            REQUIRE( Catch::alwaysTrue() );
         }
     }
 }
diff --git a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj
index c5dfcc8..a8dae9f 100644
--- a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj
+++ b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj
@@ -61,6 +61,8 @@
 		261488FD184D21290041FBEB /* catch_section_info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_section_info.h; sourceTree = "<group>"; };
 		261488FE184DC32F0041FBEB /* catch_section.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_section.h; sourceTree = "<group>"; };
 		261488FF184DC4A20041FBEB /* catch_debugger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_debugger.h; sourceTree = "<group>"; };
+		2627F7051935B16F009BCE2D /* catch_result_builder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_result_builder.h; sourceTree = "<group>"; };
+		2627F7061935B55F009BCE2D /* catch_result_builder.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_result_builder.hpp; sourceTree = "<group>"; };
 		262E7399184673A800CAC268 /* catch_reporter_bases.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_bases.hpp; sourceTree = "<group>"; };
 		262E739A1846759000CAC268 /* catch_common.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_common.hpp; sourceTree = "<group>"; };
 		263FD06017AF8DF200988A20 /* catch_timer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_timer.hpp; sourceTree = "<group>"; };
@@ -104,7 +106,7 @@
 		4A4B0F9915CE6EC100AE2392 /* catch_interfaces_registry_hub.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_interfaces_registry_hub.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
 		4A4B0F9A15CEF84800AE2392 /* catch_notimplemented_exception.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_notimplemented_exception.h; sourceTree = "<group>"; };
 		4A4B0F9B15CEF8C400AE2392 /* catch_notimplemented_exception.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_notimplemented_exception.hpp; sourceTree = "<group>"; };
-		4A4B0F9C15CEFA8300AE2392 /* catch_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_impl.hpp; sourceTree = "<group>"; };
+		4A4B0F9C15CEFA8300AE2392 /* catch_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_impl.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
 		4A6D0C20149B3D3B00DB3EAA /* CatchSelfTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CatchSelfTest; sourceTree = BUILT_PRODUCTS_DIR; };
 		4A6D0C26149B3D3B00DB3EAA /* CatchSelfTest.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = CatchSelfTest.1; sourceTree = "<group>"; };
 		4A6D0C2D149B3D9E00DB3EAA /* ApproxTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ApproxTests.cpp; path = ../../../SelfTest/ApproxTests.cpp; sourceTree = "<group>"; };
@@ -169,7 +171,6 @@
 		4AB77CB71553B72B00857BF0 /* catch_section_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_section_info.hpp; sourceTree = "<group>"; };
 		4ABEA80415C90D2B009F0424 /* catch_objc_arc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_objc_arc.hpp; sourceTree = "<group>"; };
 		4AC91CCE155CF02800DC5117 /* catch_expression_lhs.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_expression_lhs.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
-		4AC91CD0155D8DA600DC5117 /* catch_expression_decomposer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_expression_decomposer.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
 		4ACE21C8166CA19700FB5509 /* catch_option.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_option.hpp; sourceTree = "<group>"; };
 		4ACE21CA166CA1B300FB5509 /* catch_option.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_option.cpp; path = ../../../SelfTest/SurrogateCpps/catch_option.cpp; sourceTree = "<group>"; };
 		4AEE031F16142F910071E950 /* catch_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_common.cpp; path = ../../../SelfTest/SurrogateCpps/catch_common.cpp; sourceTree = "<group>"; };
@@ -342,6 +343,7 @@
 				4A90B59E15D2521E00EF71BC /* catch_expressionresult_builder.hpp */,
 				4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */,
 				26847E5C16BBACB60043B9C1 /* catch_message.hpp */,
+				2627F7061935B55F009BCE2D /* catch_result_builder.hpp */,
 			);
 			name = impl;
 			sourceTree = "<group>";
@@ -361,10 +363,10 @@
 				4A6D0C46149B3E3D00DB3EAA /* catch_approx.hpp */,
 				4A6D0C47149B3E3D00DB3EAA /* catch_capture.hpp */,
 				4AC91CCE155CF02800DC5117 /* catch_expression_lhs.hpp */,
-				4AC91CD0155D8DA600DC5117 /* catch_expression_decomposer.hpp */,
 				4A4B0F9A15CEF84800AE2392 /* catch_notimplemented_exception.h */,
 				26847E5B16BBAB790043B9C1 /* catch_message.h */,
 				261488FD184D21290041FBEB /* catch_section_info.h */,
+				2627F7051935B16F009BCE2D /* catch_result_builder.h */,
 			);
 			name = Assertions;
 			sourceTree = "<group>";