mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +01:00 
			
		
		
		
	Experimental static analysis support in TEST_CASE and SECTION
Closes #2681
This commit is contained in:
		| @@ -9,6 +9,7 @@ | ||||
| #define CATCH_SECTION_HPP_INCLUDED | ||||
|  | ||||
| #include <catch2/internal/catch_compiler_capabilities.hpp> | ||||
| #include <catch2/internal/catch_config_static_analysis_support.hpp> | ||||
| #include <catch2/internal/catch_noncopyable.hpp> | ||||
| #include <catch2/catch_section_info.hpp> | ||||
| #include <catch2/catch_timer.hpp> | ||||
| @@ -38,16 +39,62 @@ namespace Catch { | ||||
|  | ||||
| } // end namespace Catch | ||||
|  | ||||
| #if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT) | ||||
| #    define INTERNAL_CATCH_SECTION( ... )                                 \ | ||||
|         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                         \ | ||||
|         CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                  \ | ||||
|     if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ | ||||
|         if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME(            \ | ||||
|                  catch_internal_Section ) =                               \ | ||||
|                  Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ | ||||
|         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION | ||||
|  | ||||
| #    define INTERNAL_CATCH_DYNAMIC_SECTION( ... )                     \ | ||||
|         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                     \ | ||||
|         CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS              \ | ||||
|     if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \ | ||||
|         if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME(        \ | ||||
|                  catch_internal_Section ) =                           \ | ||||
|                  Catch::SectionInfo(                                  \ | ||||
|                      CATCH_INTERNAL_LINEINFO,                         \ | ||||
|                      ( Catch::ReusableStringStream() << __VA_ARGS__ ) \ | ||||
|                          .str() ) )                                   \ | ||||
|         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION | ||||
|  | ||||
| #else | ||||
|  | ||||
| // These section definitions imply that at most one section at one level | ||||
| // will be intered (because only one section's __LINE__ can be equal to | ||||
| // the dummy `catchInternalSectionHint` variable from `TEST_CASE`). | ||||
|  | ||||
| namespace Catch { | ||||
|     namespace Detail { | ||||
|         // Intentionally without linkage, as it should only be used as a dummy | ||||
|         // symbol for static analysis. | ||||
|         int GetNewSectionHint(); | ||||
|     } // namespace Detail | ||||
| } // namespace Catch | ||||
|  | ||||
|  | ||||
| #    define INTERNAL_CATCH_SECTION( ... )                                   \ | ||||
|         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                           \ | ||||
|         CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                    \ | ||||
|         CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                             \ | ||||
|         if ( [[maybe_unused]] int catchInternalPreviousSectionHint =        \ | ||||
|                  catchInternalSectionHint,                                  \ | ||||
|              catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \ | ||||
|              catchInternalPreviousSectionHint == __LINE__ )                 \ | ||||
|         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION | ||||
|  | ||||
| #    define INTERNAL_CATCH_DYNAMIC_SECTION( ... )                           \ | ||||
|         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                           \ | ||||
|         CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                    \ | ||||
|         CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                             \ | ||||
|         if ( [[maybe_unused]] int catchInternalPreviousSectionHint =        \ | ||||
|                  catchInternalSectionHint,                                  \ | ||||
|              catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \ | ||||
|              catchInternalPreviousSectionHint == __LINE__ )                 \ | ||||
|         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #endif // CATCH_SECTION_HPP_INCLUDED | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #ifndef CATCH_TEST_REGISTRY_HPP_INCLUDED | ||||
| #define CATCH_TEST_REGISTRY_HPP_INCLUDED | ||||
|  | ||||
| #include <catch2/internal/catch_config_static_analysis_support.hpp> | ||||
| #include <catch2/internal/catch_source_line_info.hpp> | ||||
| #include <catch2/internal/catch_noncopyable.hpp> | ||||
| #include <catch2/interfaces/catch_interfaces_test_invoker.hpp> | ||||
| @@ -72,6 +73,9 @@ struct AutoReg : Detail::NonCopyable { | ||||
|         void TestName::test() | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT) | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////////// | ||||
|     #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ | ||||
|         static void TestName(); \ | ||||
| @@ -84,19 +88,40 @@ struct AutoReg : Detail::NonCopyable { | ||||
|     #define INTERNAL_CATCH_TESTCASE( ... ) \ | ||||
|         INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__ ) | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////////// | ||||
|     #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ | ||||
| #else  // ^^ !CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | vv CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | ||||
|  | ||||
|  | ||||
| // Dummy registrator for the dumy test case macros | ||||
| namespace Catch { | ||||
|     namespace Detail { | ||||
|         struct DummyUse { | ||||
|             DummyUse( void ( * )( int ) ); | ||||
|         }; | ||||
|     } // namespace Detail | ||||
| } // namespace Catch | ||||
|  | ||||
| // Note that both the presence of the argument and its exact name are | ||||
| // necessary for the section support. | ||||
|  | ||||
| // We provide a shadowed variable so that a `SECTION` inside non-`TEST_CASE` | ||||
| // tests can compile. The redefined `TEST_CASE` shadows this with param. | ||||
| static int catchInternalSectionHint = 0; | ||||
|  | ||||
| #    define INTERNAL_CATCH_TESTCASE2( fname )                              \ | ||||
|         static void fname( int );                                          \ | ||||
|         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                          \ | ||||
|         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                           \ | ||||
|         CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                   \ | ||||
|         namespace {                                                           \ | ||||
|         const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \ | ||||
|             Catch::makeTestInvoker( &QualifiedMethod ),                   \ | ||||
|             CATCH_INTERNAL_LINEINFO,                                      \ | ||||
|             "&" #QualifiedMethod##_catch_sr,                              \ | ||||
|             Catch::NameAndTags{ __VA_ARGS__ } );                          \ | ||||
|     } /* NOLINT */ \ | ||||
|         static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME(   \ | ||||
|             dummyUser )( &fname );                                         \ | ||||
|         CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                            \ | ||||
|         static void fname( [[maybe_unused]] int catchInternalSectionHint ) \ | ||||
|             CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION | ||||
| #    define INTERNAL_CATCH_TESTCASE( ... ) \ | ||||
|         INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ) ) | ||||
|  | ||||
|  | ||||
| #endif // CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////////// | ||||
|     #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ | ||||
| @@ -118,6 +143,22 @@ struct AutoReg : Detail::NonCopyable { | ||||
|     #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ | ||||
|         INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ ) | ||||
|  | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////////// | ||||
|     #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ | ||||
|         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ | ||||
|         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ | ||||
|         CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ | ||||
|         namespace {                                                           \ | ||||
|         const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \ | ||||
|             Catch::makeTestInvoker( &QualifiedMethod ),                   \ | ||||
|             CATCH_INTERNAL_LINEINFO,                                      \ | ||||
|             "&" #QualifiedMethod##_catch_sr,                              \ | ||||
|             Catch::NameAndTags{ __VA_ARGS__ } );                          \ | ||||
|     } /* NOLINT */ \ | ||||
|         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION | ||||
|  | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////////// | ||||
|     #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ | ||||
|         do { \ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Martin Hořeňovský
					Martin Hořeňovský