84
84
#include < tuple>
85
85
#include < type_traits>
86
86
#include < typeindex>
87
- #include < typeinfo>
87
+ #ifndef CPP2_NO_RTTI
88
+ #include < typeinfo>
89
+ #endif
88
90
#include < utility>
89
91
#include < variant>
90
92
#include < memory>
100
102
#include < limits>
101
103
#include < cassert>
102
104
#include < cerrno>
103
- #include < exception>
105
+ #ifndef CPP2_NO_EXCEPTIONS
106
+ #include < exception>
107
+ #endif
104
108
#include < stdexcept>
105
109
#include < system_error>
106
110
#include < cctype>
194
198
// Otherwise, we're not in -pure-cpp2 and so just #include
195
199
// what we need in this header to make this self-contained
196
200
#else
197
- #include < exception>
198
201
#include < type_traits>
199
202
#include < new>
200
203
#include < memory>
209
212
#include < cstdio>
210
213
#include < cstdint>
211
214
215
+ #ifndef CPP2_NO_EXCEPTIONS
216
+ #include < exception>
217
+ #endif
218
+ #ifndef CPP2_NO_RTTI
219
+ #include < typeinfo>
220
+ #endif
221
+
212
222
#if defined(CPP2_USE_SOURCE_LOCATION)
213
223
#include < source_location>
214
224
#endif
@@ -371,6 +381,78 @@ auto assert_in_bounds(auto&& x, auto&& arg CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAU
371
381
}
372
382
373
383
384
+ // -----------------------------------------------------------------------
385
+ //
386
+ // Support wrappers that unblock using this file in environments that
387
+ // disable EH or RTTI
388
+ //
389
+ // Note: This is not endorsing disabling those features, it's just
390
+ // recognizing that disabling them is popular (e.g., games, WASM)
391
+ // and so we should remove a potential adoption blocker... only a
392
+ // few features in this file depend on EH or RTTI anyway, and
393
+ // wouldn't be exercised in such an environment anyway so there
394
+ // is no real net loss here
395
+ //
396
+ // -----------------------------------------------------------------------
397
+ //
398
+
399
+ [[noreturn]] auto Throw (auto && x, [[maybe_unused]] char const * msg) -> void {
400
+ #ifdef CPP2_NO_EXCEPTIONS
401
+ Type.expects (
402
+ !" exceptions are disabled with -fno-exceptions" ,
403
+ msg
404
+ );
405
+ std::terminate ();
406
+ #else
407
+ throw CPP2_FORWARD (x);
408
+ #endif
409
+ }
410
+
411
+ auto Uncaught_exceptions () -> int {
412
+ #ifdef CPP2_NO_EXCEPTIONS
413
+ return 0 ;
414
+ #else
415
+ return std::uncaught_exceptions ();
416
+ #endif
417
+ }
418
+
419
+ template <typename T>
420
+ auto Dynamic_cast ( [[maybe_unused]] auto && x ) -> decltype(auto ) {
421
+ #ifdef CPP2_NO_RTTI
422
+ Type.expects (
423
+ !" 'as' dynamic casting is disabled with -fno-rtti" , // more likely to appear on console
424
+ " 'as' dynamic casting is disabled with -fno-rtti" // make message available to hooked handlers
425
+ );
426
+ return nullptr ;
427
+ #else
428
+ return dynamic_cast <T>(CPP2_FORWARD (x));
429
+ #endif
430
+ }
431
+
432
+ template <typename T>
433
+ auto Typeid () -> decltype(auto ) {
434
+ #ifdef CPP2_NO_RTTI
435
+ Type.expects (
436
+ !" 'any' dynamic casting is disabled with -fno-rtti" , // more likely to appear on console
437
+ " 'any' dynamic casting is disabled with -fno-rtti" // make message available to hooked handlers
438
+ );
439
+ #else
440
+ return typeid (T);
441
+ #endif
442
+ }
443
+
444
+ // We don't need typeid(expr) yet -- uncomment this if/when we need it
445
+ // auto Typeid( [[maybe_unused]] auto&& x ) -> decltype(auto) {
446
+ // #ifdef CPP2_DISABLE_RTTI
447
+ // Type.expects(
448
+ // !"<write appropriate error message here>"
449
+ // );
450
+ // #else
451
+ // return typeid(CPP2_FORWARD(x));
452
+ // #endif
453
+ // }
454
+
455
+
374
456
// -----------------------------------------------------------------------
375
457
//
376
458
// Arena objects for std::allocators
@@ -457,7 +539,7 @@ class out {
457
539
bool has_t ;
458
540
459
541
// Each out in a chain contains its own uncaught_count ...
460
- int uncaught_count = std::uncaught_exceptions ();
542
+ int uncaught_count = Uncaught_exceptions ();
461
543
// ... but all in a chain share the topmost called_construct_
462
544
bool called_construct_ = false ;
463
545
@@ -477,7 +559,7 @@ class out {
477
559
// In the case of an exception, if the parameter was uninitialized
478
560
// then leave it in the same state on exit (strong guarantee)
479
561
~out () {
480
- if (called_construct () && uncaught_count != std::uncaught_exceptions ()) {
562
+ if (called_construct () && uncaught_count != Uncaught_exceptions ()) {
481
563
Default.expects (!has_t );
482
564
dt->destroy ();
483
565
called_construct () = false ;
@@ -589,6 +671,7 @@ class out {
589
671
//
590
672
// -----------------------------------------------------------------------
591
673
//
674
+
592
675
// -------------------------------------------------------------------------------------------------------------
593
676
// Built-in is
594
677
//
@@ -652,7 +735,7 @@ template< typename C, typename X >
652
735
( std::is_polymorphic_v<C> && std::is_polymorphic_v<X>)
653
736
) && !std::is_same_v<C,X>)
654
737
auto is( X const & x ) -> bool {
655
- return dynamic_cast <C const *>(&x) != nullptr ;
738
+ return Dynamic_cast <C const *>(&x) != nullptr ;
656
739
}
657
740
658
741
template < typename C, typename X >
@@ -661,7 +744,7 @@ template< typename C, typename X >
661
744
( std::is_polymorphic_v<C> && std::is_polymorphic_v<X>)
662
745
) && !std::is_same_v<C,X>)
663
746
auto is( X const * x ) -> bool {
664
- return dynamic_cast <C const *>(x) != nullptr ;
747
+ return Dynamic_cast <C const *>(x) != nullptr ;
665
748
}
666
749
667
750
template < typename C, typename X >
@@ -814,25 +897,25 @@ auto as( X&& x ) -> C&& {
814
897
template < typename C, typename X >
815
898
requires (std::is_base_of_v<X, C> && !std::is_same_v<C,X>)
816
899
auto as( X& x ) -> C& {
817
- return dynamic_cast <C&>(x);
900
+ return Dynamic_cast <C&>(x);
818
901
}
819
902
820
903
template < typename C, typename X >
821
904
requires (std::is_base_of_v<X, C> && !std::is_same_v<C,X>)
822
905
auto as( X const & x ) -> C const & {
823
- return dynamic_cast <C const &>(x);
906
+ return Dynamic_cast <C const &>(x);
824
907
}
825
908
826
909
template < typename C, typename X >
827
910
requires (std::is_base_of_v<X, C> && !std::is_same_v<C,X>)
828
911
auto as( X* x ) -> C* {
829
- return dynamic_cast <C*>(x);
912
+ return Dynamic_cast <C*>(x);
830
913
}
831
914
832
915
template < typename C, typename X >
833
916
requires (std::is_base_of_v<X, C> && !std::is_same_v<C,X>)
834
917
auto as( X const * x ) -> C const * {
835
- return dynamic_cast <C const *>(x);
918
+ return Dynamic_cast <C const *>(x);
836
919
}
837
920
838
921
@@ -978,7 +1061,7 @@ auto as( std::variant<Ts...> const& x ) {
978
1061
if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<17 >(x)), T >) { if (x.index () == 17 ) return operator_as<7 >(x); }
979
1062
if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<18 >(x)), T >) { if (x.index () == 18 ) return operator_as<8 >(x); }
980
1063
if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<19 >(x)), T >) { if (x.index () == 19 ) return operator_as<9 >(x); }
981
- throw std::bad_variant_access ();
1064
+ Throw ( std::bad_variant_access (), " 'as' cast failed for 'variant' " );
982
1065
}
983
1066
984
1067
@@ -1264,7 +1347,7 @@ inline auto fopen( const char* filename, const char* mode ) {
1264
1347
#endif
1265
1348
1266
1349
if (!x) {
1267
- throw std::make_error_condition (std::errc::no_such_file_or_directory);
1350
+ Throw ( std::make_error_condition (std::errc::no_such_file_or_directory), " 'fopen' attempt failed " );
1268
1351
}
1269
1352
return c_raii ( x, &fclose );
1270
1353
}
0 commit comments