Skip to content
  • Michael Tautschnig's avatar
    Insert assert(0) into the body of reach_error · 07dd9f37
    Michael Tautschnig authored
    As discussed in the (virtual) community meeting on 2020-09-18,
    unreach-call may be turned into plain assertion checking. As first step,
    make the body of reach_error() `assert(0);`. For preprocessed files, the
    result of assert(0) expansion is what we get on Ubuntu 18.04 with glibc
    and GCC 7.5.0.
    
    This change was previously made in 7341f59b, which did not properly handle
    the case of reach_error not being defined in the main source file. This
    commit now only handle files that do define it in the main source file. Other
    tasks will be handled in a separate commit.
    
    The changes were done using the following command:
    ```
    for f in c/*/*.c
    do
    export bn=$(basename $f .c)
    dn=$(dirname $f)
    test -e $dn/$bn.i
    export p=$?
    perl -i -e \
      '$p = $ENV{p}; $i = 0; $e = 0;
       while(<>) {
         $i++;
         if(p == 0 && /^#include\s*<assert.h>/) {
           $p = 2;
         }
         elsif(p == 1 && /^extern void __assert_fail/) {
           $p = 3;
         }
         elsif(/^void reach_error\(\)\s*\{\}\s*$/) {
           if($p == 0) {
             print "#include <assert.h>\n";
             $i++;
             $p = 2;
           }
           elsif($p == 1) {
             print "extern void __assert_fail(const char *, const char *, ";
             print "unsigned int, const char *) ";
             print "__attribute__ ((__nothrow__ , __leaf__)) ";
             print "__attribute__ ((__noreturn__));\n";
             $i++;
             $p = 3;
           }
           if($p == 2) {
             print "void reach_error() { assert(0); }\n";
           }
           elsif($p == 3) {
             print "void reach_error() { __assert_fail(\"0\", \"";
             print $ENV{bn};
             print ".c\", $i, \"reach_error\"); }\n";
           }
           $e = 1;
           next;
         }
         print;
       }
       exit $e;' \
      $f && continue
    [ $p -eq 0 ] || continue
    export i=$(grep -n '^void reach_error' $f | cut -f1 -d:)
    perl -i -e \
      '$p = 1; $i = $ENV{i} != "" ? $ENV{i} : 0;
       while(<>) {
         if(/^extern void __assert_fail/) {
           $p = 3;
         }
         elsif(/^void reach_error\(\)\s*\{\}\s*$/) {
           if($p == 1) {
             print <<'END_ASSERT';
    
    extern void __assert_fail (const char *__assertion, const char *__file,
          unsigned int __line, const char *__function)
         __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
    extern void __assert_perror_fail (int __errnum, const char *__file,
          unsigned int __line, const char *__function)
         __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
    extern void __assert (const char *__assertion, const char *__file, int __line)
         __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__));
    
    END_ASSERT
             $p = 3;
           }
           if($p == 3) {
             print "void reach_error() { ((void) sizeof ((0) ? 1 : 0), ";
             print "__extension__ ({ if (0) ; else __assert_fail (\"0\", \"";
             print $ENV{bn};
             print ".c\", $i, __extension__ __PRETTY_FUNCTION__); })); }\n";
           }
           next;
         }
         print;
       }' \
      $dn/$bn.i
    done
    ```
    07dd9f37