Astrée and RuleChecker Release 21.10 Improved precision * Improved precision of: - the congruence interval domain - the interpolation domain on typical interpolation code patterns - widening for non-relational domains - widening heuristics for integers and floating-point values - the modulo operator % used in conditions - offsetof for the code pattern &((S*) NULL)->field - float comparisons in cases where one of the arguments can be NaN, ∞, or −∞ * Improved the heuristics for octagon packing and the precision of the octagon domain with respect to multiplication. * Variables that are subject to __ASTREE_global_assert now retain their globally asserted bounds, even when affected by data races. * If the option cut-write-to-const is enabled, then write_to_constant_memory alarms are used to sharpen the analysis information such that affected pointers cannot point to definitely const memory afterwards. * When representing values that may be either integers or pointers, Astrée now prefers precision on pointer offset information over precision on integer values. * Improved precision of modulo-intervals such that intervals with outlier values like [0,16] U {255} can be represented precisely in many cases. * Improved precision for analysis projects with data race alarms or __ASTREE_absolute_address directives. Weighted findings To grade alarms according to their significance, findings are now extended by a new attribute “weight”. The weight can be displayed in an extra column in the Findings view. It is hidden by default and can be enabled from the context menu by right-clicking on the table header. The findings can also be filtered according to their weight from Overview -> Filter. The corresponding DAX tag is <threshold kind="weight">. The weight can be exported to the XML report and custom report files using the DAX element <include-weight threshold="value">. Improved tooltips * Tooltips now show information provided by the congruence interval domain. * Tooltips now show more precise interval information for floats. If a lower bound on the absolute value is known, then two intervals are displayed: one with negative, and one with positive range. Improved directives * New directive __ASTREE_partition_calls(()) that partitions function calls in any declaration or the statement that directly follows it. For if, switch, for, while, and do-while statements, it only partitions function calls in the condition expression. * __ASTREE_partition_control now also works when placed in front of a switch statement whose body starts with declarations. * __ASTREE_modify((x; full_range)) no longer stops the analysis of the current context if x is const. * __ASTREE_attributes now accepts a new attribute hide_directives which omits Astrée directives in scope from the lists of semantic hypotheses and further directives. The new attribute is intended for use in stub libraries. * __ASTREE_alarm and __ASTREE_print now support printing of pointers and strings. For example, the code const char* mystr = "hello"; const char* myptr = mystr + 3; __ASTREE_print(("%s0, %1", mystr, myptr)); results in the following output in both the analyzer log and the text report file: {hello}, {__ASTREEstring.hello.0} + {3} at <program-location> * __ASTREE_partition_ranges now accepts a slice of integer values: __ASTREE_partition_ranges((var; {0 : 5})); which is equivalent to: __ASTREE_partition_ranges((var; 0, 1, 2, 3, 4, 5)); * __ASTREE_boolean_pack can now be used with bit-fields. For example: struct T {int a; unsigned b:1;} v; __ASTREE_boolean_pack((v.a; v.b)); * __ASTREE_attribute now accepts the new argument "forbid_separate" that prevents affected functions from being analyzed separately. It has the same effect as listing them as "forbid=<function>" in the separate-function option. The separate-function option takes precedence over forbid_separate attributes. * Improved performance of __ASTREE_modify if the first argument is a large unsmashed array. General improvements * Improved handling of file names in the file metrics table of the text report file and analyzer log. * Memory usage statistics are now also displayed after each separate iteration over main. * Improved reported source location for alarms about arguments of Astrée intrinsic functions such as __astree_memcpy(). * When displaying the computed separate functions for a given process, Astrée now also displays the current asynchronous phase, if phases are active. * If a definite run-time error is raised on a statement for which Astrée reports several alarms of class A, then all of these alarms are now marked as potentially related in the Findings view. An additional "group ID" identifies all alarms that possibly trigger the same definite run-time error. For example: Definite Alarm (A) Group 1 ... ALARM (A) invalid_pointer_dereference:... Definite Alarm (A) Group 1 ... ALARM (A) overflow_upon_dereference:... * The option separate-with-caller-stack-pointers has been removed. The analyzer now behaves as if the option was enabled. * Updated the Astrée option profiles "Setup (fast)" and "Setup (normal)". * Improved the efficiency of the directives __ASTREE_global_assert and __ASTREE_volatile_input when applied to large arrays. * When a process attempts to stop another process using the analyzer-intrinsic function __astree_stop_process(process_id), Astrée now emits an alarm message and ignores the intrinsic. * Optimized the generation of absolute address directives when enabling the option generate-absolute-addresses. It now generates distinct directives for separate contiguous memory blocks up to a size limit. The new heuristic reduces the impact of the generated directives on the performance of the analysis. * Dynamic folding no longer folds parts of variables with different value ranges. Note that the directive __ASTREE_global_assert modifies the range of a variable. In other words, if a[i] is affected by an __ASTREE_global_assert, but a[j] is not, then a is no longer dynamically folded. Improvements for C * The new option warn-on-float-to-unsigned-conversion-trap enables alarms on conversions from float to unsigned integer, if values are in the interval (-1, 0). The option is disabled by default. If enabled, the new alarm float_to_unsigned_conversion_trap warns about such conversions that may trigger trap events on some architectures. * In the wrapper and stubs file it is now possible in all Astrée directives to refer to static variables of other translation units (using var@"file.c"), as long as a preceding __ASTREE_import(()); directive is present. * In the wrapper and stubs file directives can now refer to variables in arbitrary functions, as long as a preceding __ASTREE_import(()); directive is present. The syntax var@fun addresses a variable named var in a function named fun. The new syntax can also be combined with the syntax for addressing static functions, as in var@fun@"file". Improvements for C++ * Documented limitations and specific behaviors of the analyzer regarding the reporting of undefined behavior in constexpr expressions, and in static and complex initializers. * Removed false alarms about possibly invalid iterators after erasing from sequence containers at the beginning. Fixes * Fixed exceptional aborts of the analyzer related to a combination of the options exclude-signed-in-unsigned-overflows=yes and symb=yes. * Fixed an issue that in rare cases when boolean-domain was activated in combination with exclude-signed-in-unsigned-overflows caused the analysis to stop for a given context with an "ERROR analysis_stopped_unexpectedly". Rule sets and checks for C * New diagnostics: - check config-function-unknown (rule A.5.4) warns about function names that are used in the Astrée option separate-function but do not name a function in the analyzed code. - rule A.7.1 warns if an identifier appears with both internal and external linkage within a translation unit, which constitutes undefined behavior - rule A.5.5 (check autosar-inclusion-order) warns about illegal header inclusion order in Astrée analysis projects that use Astrée’s AUTOSAR OS stubs. It warns about #include directives that attempt to include the real Os.h or osek.h header files before the corresponding header file stubs for Astrée. * Added support for rule M2012.D.4.8. * The new check constant-out-of-range (rule M2012.1.1, M.1.1) warns about constants that do not fit into the range of their type. * Added new checks for RuleChecker in combination with Astrée: - invalid-pointer-arithmetics - dangling-pointer-use - left-shift-negative-first-argument - undefined-shift-width - offset-overflow - function-pointer-wrong-argument-count - misaligned-dereference - function-pointer-incompatible-return-type - invalid-function-pointer - int-undefined-modulo The new checks are associated with rule M2012.1.3 and M.1.2, and correspond to the following Astrée alarms: - invalid-pointer-arithmetics - dangling-pointer-use - shift-first-argument - shift-argument - offset-overflow - wrong-argument-count - misaligned-dereference - (reinterpret-)incompatible-return-type - invalid-function-pointer - int-undefined-modulo Clang Static Analyzer This new analysis phase runs checks provided by the Clang Static Analyzer. It is deactivated by default and can be enabled by setting the new option skip-clang-static-analyzer-phase to "no". The following new checks are available: - csa-dead-assignment - csa-call-uninitialized-function-pointer - csa-call-uninitialized-object-pointer - csa-call-null-function-pointer - csa-call-null-object-pointer - csa-division-by-zero - csa-null-reference-param - csa-null-dereference - csa-double-free - csa-use-after-free - csa-uninitialized-binop-operand - csa-uninitialized-array-subscript - csa-uninitialized-assign - csa-uninitialized-branch-condition - csa-uninitialized-return - csa-uninitialized-object - csa-memory-leak - csa-mismatched-deallocator - csa-placement-new - csa-stack-address-escape These new checks are associated with the following rules for C++: - AUTOSAR.0.1.1A - AUTOSAR.3.8.1A - AUTOSAR.5.3.2A - AUTOSAR.5.6.1A - AUTOSAR.7.5.1M - AUTOSAR.8.5.0A - AUTOSAR.18.5.6A - AUTOSAR.18.5.10A - CERT-CPP.ARR.30C - CERT-CPP.DCL.30C - CERT-CPP.34C - CERT-CPP.EXP.53 - CERT-CPP.EXP.54 - CERT-CPP.INT.33C - CERT-CPP.MEM.30C - CERT-CPP.MEM.31C - CERT-CPP.MEM.50 - CERT-CPP.MEM.51 - CERT-CPP.MEM.54 - M2008.0.1.6 - M2008.7.5.1 - M2008.8.5.1 AUTOSAR * Added support for the following AUTOSAR rules: - AUTOSAR.0.1.1A - AUTOSAR.0.4.4A - AUTOSAR.3.1.6A - AUTOSAR.5.3.2A - AUTOSAR.5.6.1A - AUTOSAR.9.6.1A - AUTOSAR.9.6.2A - AUTOSAR.13.5.4A - AUTOSAR.17.6.1A - AUTOSAR.18.5.4A - AUTOSAR.18.5.6A - AUTOSAR.0.1.5A * The rule AUTOSAR.6.2.1M can now be configured to ignore the operands of the comma operator if their values are not used. SEI CERT C++ Added support for the following SEI CERT C++ rules: - CERT-CPP.EXP.34C - CERT-CPP.INT.33C - CERT-CPP.MEM.30C - CERT-CPP.MEM.31C - CERT-CPP.MEM.50 - CERT-CPP.MEM.51 - CERT-CPP.MEM.54 MISRA C++ 2008 * Added support for rule M2008.0.1.6. * The rule M2008.6.2.1 can now be configured to ignore the operands of the comma operator if their values are not used. C++ diagnostics Added a new C++-specific category of diagnostics rules (A.CPP), available for both RuleChecker and Astrée. - A.CPP.7.1 warns about non-void functions with a path to the end of the function without a final return statement. - A.CPP.7.2 warns about violations of the One Definition Rule. Enhancements, clarifications, refinements and fixes Improved reported source location for rule violations that refer to implicit conversions applied to the right-hand side of assignments or to the expression of a return statement. — For rule checks on C code * Removed false positives for the check unused-suppress-directive, which no longer reports comment/suppress directives that apply to a violation of check unused-suppress-directive. * Corrected the assumed sizes of types that are affected by the option allow-signed-constant-with-unsigned=yes. The fix affects rules based on MISRA's essential type system in case that the option is set. The option is disabled by default. * Fixed commenting of RuleChecker alarms at non-defining declarations. * Fixed an issue that prevented constant expression evaluation when using a bitwise shift operator (<<, >>) with a right-hand side greater or equal to half the bitsize of the left-hand side, and setting the ABI option bits_per_byte to 16. * The check stdlib-limits without Astrée analysis now covers the long double variants of mathematical functions. This affects rule M2012.D.4.11, M.20.3, and CERT.FLP.32. * Improved the handling of __ASTREE_import directives. Erroneous uses are reported as violations of diagnostic rule A.5.1 instead of causing fatal tool errors or crashes. * Improved the LSCOPE metric to never underestimate the number of distinct constant values. This eliminates false negatives for the check max-language-scope (T.13.1). * Removed false negatives for the check extern-object-declaration (rule M2012.8.4) which failed to report tentative definitions that are not followed by another definition. Example: // ... no declaration of x int x; // tentative definition of x -> non-compliant, now reported // ... no definition of x * Corrected the classification of rule M2008.5.19.1 and AUTOSAR.5.19.1M. Not all cases of unsigned wrap-around during constant evaluation are reported by Astrée. * Rule M2012.1.3 and M.1.2 now additionally link the checks field-overflow-upon-dereference, float-division-by-zero, incompatible-argument-type, int-division-by-zero, int-modulo-by-zero, null-dereferencing, overflow-upon-dereference, pointer-comparison, pointer-subtraction, read-data-race, uninitialized-variable-use, write-data-race, write-to-constant-memory. * Improved source locations reported with the check undefined-extern. Array declarators are no longer part of the reported source extent. * Improved the check max-externals to report the translation unit exceeding the limit and stating the actual number of external declarations. * Improved reported location information for C expressions using a unary plus operator. * Removed false positives for: - unused-tag and identifier-unique-tag, which in rare cases misclassified the use of a struct tag as a definition - bitfield-typing, which in release 21.04i (build 9394592 and 9410978) reported bitfields using a typedef of explicitly signed short, long, and long long - external-file-spreading (AUTOSAR.3.2.3M, CERT-CPP.DCL.60, M.8.8, M2008.3.2.3, M2012.8.5) when operating on case-insensitive file systems in analysis projects that use files with names that only differ in capitalization. * Removed false negatives for: - type-compatibility-link (A.1.1, CERT.DCL.40, CERT.MSC.40, ISO17961.funcdecl, M.1.1, M.8.4, M2012.1.1, M2012.D.2.1), which did not warn about tentative definitions of objects without preceding declaration in the same translation unit - controlling-invariant at the first operand of ? : — For rule checks on C++ code * The check include_position (M2008.16.0.1, AUTOSAR.16.0.1M) has been split into two checks to allow for a more fine-grained configuration: - include_position_language_linkage warns about #include directives preceded by language linkage specifications (i.e. extern "C"). - include_position no longer warns about #include directives preceded by language linkage specifications * Removed false positives for: - main-function-catch-all (AUTOSAR.15.3.3A, CERT-CPP.ERR.51, M2008.15.3.2, M2008.15.5.3), which warned about non-defining declarations of the main function. - underlying-cvalue-conversion (AUTOSAR.5.0.3M, M2008.5.0.3) warning about compliant pointer arithmetic in C++. - output-parameter and multiple_output_values (AUTOSAR.8.4.8A, AUTOSAR.8.4.4A). Parameters of lvalue-reference or pointer type are only considered output parameters if they are modified but never read in the function body. Rule AUTOSAR.8.4.8A and AUTOSAR.8.4.4A are classified as partially checked. - definition-duplicate for user-defined new and delete operators. They replace the default definitions from the standard library without conflict. * Fixed false positives and false negatives in the check definition-duplicate when dealing with variable templates (affects M2008.3.2.2, M2008.3.2.4, AUTOSAR.3.2.2M, AUTOSAR.3.2.4M, CERT-CPP.DCL.60). * The coverage classification of AUTOSAR.3.2.4M and M2008.3.2.4 is set to partially checked. * More compact C++ names, in particular with respect to template arguments that match the default arguments. * Improved detection of constant C++ expressions. This removes false positives for AUTOSAR.12.1.3A and AUTOSAR.3.3.2A. New DAX version 1.13 * Rule, option, and ABI tags no longer accept comma-separated lists of parameters. The <item/> list syntax is now mandatory. For example, the old specification <substitute-functions>aa=bb,cc=dd</substitute-functions> must now be written as: <substitute-functions> <item key="aa">bb</item> <item key="cc">dd</item> </substitute-functions> * In addition to requiring the <item/> list syntax, the tags for rules now use "enabled" attributes to express (de-)activation of rules. For example, the old specification <RULENAME value="AA, BB">yes</RULENAME> must now be written as: <RULENAME enabled="yes"> <value> <item>AA</item> <item>BB</item> </value> </RULENAME> * The tags for checks are now (de-)activated using the attribute "enabled". For example, the old specification <CHECKNAME>yes</CHECKNAME> must now be written as <CHECKNAME enabled="yes"/> * The "file" attribute in the tags <options> and <abi> is no longer supported. * The new DAX tag <result-filter/> allows the automatic configuration of the "Overview -> Filter" settings of the client. The filter settings are stored persistently with the analysis project. * Corrected the resolution of relative paths when importing contents from other DAX files. A relative path is now always resolved relative to the (possibly implicit) global base directory of the DAX file in which the path is specified. General improvements * The directives __ASTREE_comment, __RULECHECKER_comment, __ASTREE_suppress, __RULECHECKER_suppress, as well as their source-directive counterparts ASTREE_comment, RULECHECKER_comment, ASTREE_suppress, RULECHECKER_suppress now support a set of finding keys instead of only a single finding key. Here is an example of the old syntax using a single finding key: __ASTREE_suppress(1, 1, check_assignment); And here is an example of the new syntax using a set of finding keys: __ASTREE_suppress(1, 1, {check_assignment, check_bitfield}); * Fixed matching of file names in source directives (ASTREE_comment and ASTREE_suppress). The previous implementation inadvertently matched multiple files if they shared the same suffix (e.g. file.cpp also matched other_file.cpp), causing an error. * Fixed the reporting of occurrences of the directive __ASTREE_import. * Updated toolchain to Clang and LLVM 12. * Improved the printing of top-level type qualifiers in alarm messages. Windows support From this release on, Astrée and RuleChecker require at least Windows 10. Integration with dSPACE TargetLink * Support for TargetLink 5.0 and 5.1. * __ASTREE_wrapper_call directives are no longer generated by the TargetLink integration. * The generated wrapper files are now more compliant with MISRA coding rules. Integration with KEIL μVision Removed erroneous quotation marks in defines passed to the preprocessor configuration. Integration with Eclipse * Configuration of parser options, such as external declarations and patterns to ignore. * Improved configuration dialog for enabled rules. * Improved handling of relative config files. * Fixed an issue with 21.04i intermediate releases that caused duplication of parser filters and external declarations imported from an external DAX file. * Improved support for linked files and folders. Client GUI, batch mode, and report files * The call graph view in both Astrée and RuleChecker can now show complete and partial call graphs for any function in the analyzed program. It is also possible to display thread-specific control flow graphs. The graphs can be interactively explored and are linked to the code and result views. * The preprocessed and original files lists in the project browser can now also be displayed hierarchically in a directory tree. Switching between the list and the tree view is done via the context menu. * In the list of preprocessed files in the project browser, the configuration file (usually called astree.cfg) can now be opened in an editor via the context menu. Server and server controller * Improved stability of network connections under load. * Improved performance of the network connection between client and server. * Fixed an issue with the server option "Block connections from remote hosts" that prevented connections from localhost. C frontend * Initializers provided with aggregate types of size 0 (language extension) are now handled consistently. For example, for int arr[0] = {23}; the initializer is ignored, as it violates the diagnostics A.1.2 and A.1.8. * Support for arbitrary constant integer expressions: - as array indices in access-path specifications of Astrée directives, - as bounds of interval specifiers in __ASTREE_global_assert. * Fixed parse errors after #pragma directives containing type specifiers. * Fixed parse errors in #pragma directives containing invalid tokens. * Improved the reporting of pointer arithmetic with variably modified types, which is not supported by Astrée. The frontend reports such expressions as violations of diagnostic rule A.5.3, and the analysis stops with an error when reaching such expressions. * In accordance with the C standard, string literals that contain a newline are no longer accepted. * Improved reporting of invalid member specifications in __ASTREE_octagon_pack and __ASTREE_boolean_pack. * The C frontend now rounds tie values to even when determining the significand of a hexadecimal floating-point constant. This corrects the parsing of hex constants such as 0x1.00000000000008p0, which lies exactly between the two double numbers 0x1.FFFFFFFFFFFFFp0 and 0x2.p0. C++ frontend * Support for the extended syntax for the directive __ASTREE_global_assert, to assert the variables and functions that a pointer may point to. * Directives that accept arguments with directive access paths now also accept access paths that address fields of unions. * Removed unjustified error messages about asm constraints. * Reworked the implementation of the new and delete operators in the C++ stub library. * Support for user-provided ABI settings that specify the alignment of basic types (e.g. alignof_short). Original C source frontend The source directive /* ASTREE_comment */ now also accepts keys of alarm category groups, such as rules_category. Stub libraries, ABIs, OS and compiler configurations * Directives from the Astrée clibrary and libcxx stub libraries are no longer listed as semantic hypotheses and further directives. This improves the visibility of directives that have been added to user code. * OS stub library files no longer count towards the analysis coverage statistics. * To ease up the setup of AUTOSAR projects, a stub file for Os.h has been added to the installation. The stub file is added automatically to the project and includes the Os.h from the project code. * Corrected the implementation of Schedule() in the OSEK stub library shipped with Astrée. It now determines the ID of the process in which it is invoked instead of always assuming an invalid ID. * The C stub library is now compatible with ABIs that set bits_of_byte=16 and bits_of_char=16. * Fixed extraction of OS hooks from ARXML. * Fixed the implementation of tmpnam and snprintf in the C stub library. * Fixed the implementation of aligned delete in the C++ stub library. * Improved C++ stub library implementation of STL containers. * Corrected the implementation of frexp and frexpf in the C stub library. * Fixed type mismatches in stub code generated for AUTOSAR OS projects. * Extended the configuration parameters for AUTOSAR OS configurations: - It is now possible to specify whether ISRs may be nested. Non-nested ISRs are treated as non-preemtible. The corresponding DAX tag is nested-isrs=yes|no - It is now possible to specify priorities for ISRs. The corresponding DAX specification is: <priorities> <priority isr="fun_name" value="1001"/> </priorities> - Reworked and extended the AUTOSAR OS configuration interface in the Preprocessor view of the GUI. - The new advanced AUTOSAR option "Declare OS objects using enum/define" specifies whether OS objects in the AUTOSAR stubs should be declared using enumerations or preprocessor defines. The corresponding DAX tag is <declaration-mode/>. * Extended support for different specification formats of non-trusted functions in ARXML files. New test cases in the Astrée QSK - qk_alarm_ float_to_unsigned_conversion_trap - qk_check_annotation_insertion_failed - qk_check_autosar_inclusion_order - qk_check_config_function_unknown - qk_check_constant_out_of_range - qk_check_dangling_pointer_use - qk_check_evaluation_order - qk_check_evaluation_order_initializer - qk_check_function_pointer_incompatible_return_type - qk_check_function_pointer_wrong_argument_count - qk_check_int_undefined_modulo - qk_check_invalid_function_pointer - qk_check_invalid_pointer_arithmetics - qk_check_left_shift_negative_first_argument - qk_check_misaligned_dereference - qk_check_multiple_volatile_accesses - qk_check_offset_overflow - qk_check_sizeof - qk_check_undefined_shift_width - qk_directive_partition_calls - qk_directive_static_variables_in_directives - qk_option_filter_asm_function - qk_option_filter_asm_preprocessor_directive - qk_option_filter_pragma_asm - qk_option_filter_pragma_inline_asm - qk_option_warn_on_float_to_unsigned_conversion_trap - qk_rule_a_5_4 - qk_rule_a_5_5 - qk_rule_m_1_2 - qk_rule_m2012_1_3 The test cases qk_directive_comment_source_external, qk_filter_pragma_asm, and qk_option_separate_with_caller_stack_pointers have been removed from the Astrée QSK. New test cases in the RuleChecker QSK - qk_check_constant_out_of_range - qk_check_include_position_language_linkage - qk_check_internal_and_external_linkage - qk_check_struct_pointer_not_opaque - qk_option_filter_asm_function - qk_option_filter_asm_preprocessor_directive - qk_option_filter_pragma_asm - qk_option_filter_pragma_inline_asm - qk_option_skip_clang_static_analyzer_phase - qk_rule_a_7_1 - qk_rule_m2012_d_4_8 - qk_check_csa_call_null_function_pointer - qk_check_csa_call_null_object_pointer - qk_check_csa_call_uninitialized_function_pointer - qk_check_csa_call_uninitialized_object_pointer - qk_check_csa_dead_assignment - qk_check_csa_division_by_zero - qk_check_csa_double_free - qk_check_csa_null_dereference - qk_check_csa_null_reference_param - qk_check_csa_memory_leak - qk_check_csa_mismatched_deallocator - qk_check_csa_placement_new - qk_check_csa_stack_address_escape - qk_check_csa_uninitialized_array_subscript - qk_check_csa_uninitialized_assign - qk_check_csa_uninitialized_binop_operand - qk_check_csa_uninitialized_branch_condition - qk_check_csa_uninitialized_object - qk_check_csa_uninitialized_return - qk_check_csa_use_after_free The test case qk_directive_comment_source_external has been removed from the RuleChecker QSK. RuleChecker QSK test cases extended to C++ - qk_check_bitop_type - qk_check_external_file_spreading - qk_check_function_ellipsis - qk_check_function_local_declarator - qk_check_hash_macro - qk_check_include_characters_backslash - qk_check_logop_side_effect - qk_check_non_directive - qk_check_macro_undefined - qk_check_numeric_char_usage - qk_check_plain_char_operator - qk_check_plain_char_usage - qk_check_sizeof - qk_check_switch_skipped_code - qk_check_union_object ------------------------------------------------------------------------------ Last updated on 29 October 2021 by alex@absint.com. Copyright 2021 AbsInt. ------------------------------------------------------------------------------ An HTML version of these release notes is available at absint.com/releasenotes/astree/21.10