Hacker News new | ask | show | jobs
by mjevans 849 days ago
If code is dead or unreached, and therefore deleted / no instructions emitted; clearly THAT is of a level a warning should cover, if not an error.
1 comments

Dead code happens all the time. Adjusting the example in my comment you're replying to:

    vector<t> v;
    v.push_back(a);
    v.push_back(b);
    v.push_back(c);
    v.push_back(d);
Let's suppose the definition of our vector here looks something like this:

    template <typename T> struct vector<t> {
      size_t len = 0;
      size_t storage_len = 0;
      T *storage = nullptr;

      void push_back(T t) {
        if (len + 1 > storage_len) {
          storage_len = storage_len ? storage_len * 2 : 1;
          storage = realloc(storage, storage_len);
        }
        storage[len] = t;
        ++len;
      }
    };
So here's what happens.

    vector<t> v;
    v.push_back(a);
    v.push_back(b);
    v.push_back(c);
    v.push_back(d);
becomes

    len = 0;
    storage_len = 0;
    storage = nullptr;

    if (len + 1 > storage_len) {
      storage_len = storage_len ? storage_len * 2 : 1;
      storage = realloc(storage, storage_len);
    }
    storage[len] = a;
    ++len;

    if (len + 1 > storage_len) {
      storage_len = storage_len ? storage_len * 2 : 1;
      storage = realloc(storage, storage_len);
    }
    storage[len] = b;
    ++len;

    if (len + 1 > storage_len) {
      storage_len = storage_len ? storage_len * 2 : 1;
      storage = realloc(storage, storage_len);
    }
    storage[len] = c;
    ++len;

    if (len + 1 > storage_len) {
      storage_len = storage_len ? storage_len * 2 : 1;
      storage = realloc(storage, storage_len);
    }
    storage[len] = d;
    ++len;
becomes

    len = 0;
    storage_len = 0;
    storage = nullptr;

    if (0 + 1 > 0) {
      storage_len = 1;
      storage = realloc(storage, 1);
    }
    storage[0] = a;
    len = 1;

    if (1 + 1 > 1) {
      storage_len = 2;
      storage = realloc(storage, 2);
    }
    storage[1] = b;
    len = 2;

    if (2 + 1 > 2) {
      storage_len = 4;
      storage = realloc(storage, 4);
    }
    storage[2] = c;
    len = 3;

    if (3 + 1 > 4) {
      storage_len = 8;
      storage = realloc(storage, 8);
    }
    storage[3] = d;
    len = 4;
In that last one, you can see that the if-expression is false and the body becomes dead code. If I understand the rule you're proposing, you want to get a warning or error for that?
As a hypothetical, lets assume there's a compiler that has a deep transformation around alloc/reallocs to optimize them when they're only fed 'static' input sizes.

    // Source by nlewycky
    template <typename T> struct vector<t> {
      size_t len = 0;
      size_t storage_len = 0;
      T *storage = nullptr;

      void push_back(T t) {
        if (len + 1 > storage_len) {
          // FIXME: what if storage_len > (size_t_max >> 1) ??
          // ? Define maximum expected growth unit? 1K? 4K? 64K?
          // Assignment from trinary op visually confusing, add ( )
          storage_len = ( storage_len ? storage_len * 2 : 1 );
          storage = realloc(storage, storage_len);
        }
        storage[len] = t;
        ++len;
      }
    };
    // 
    vector<t> v;
    v.push_back(a);
    v.push_back(b);
    v.push_back(c);
    v.push_back(d);
After inlining all 4 times, the compiler might notice that in this code section vector<t> v always reaches the final size of storage = realloc(storage, 8); and optimize for that.

    // Pseudo code
    template <typename T> vector<T> v = {
      // final state at end of code section
      size_t len = 4;
      size_t storage_len = 8;
      T *storage = realloc(NULL, storage_len);
    };
    // Compiled and included, forgot template function syntax.
    void template <typename T> vector<T>.push_back(T t);
    (v[0], v[1], v[2], v[3]) = (a, b, c, d);
Even in this case, all the code the programmer wrote was evaluated and had side effects at least once at compile time. No code was eliminated as unreachable / impossible to reach. Instead it was optimized into operations that would always occur, barring realloc failure (which wasn't specified in the toy source, but would probably be a fatal error).
No, because the code as it was written is still evaluated and executed. Said execution happened to become static at the time the program was compiled and 3 out of the 4 times it was executed an effect and binary output was generated.

In all the cases that the hypothetical -Wubelim would cover the written code would be evaluated by the compiler and 'as it's undefined it can't ever be true, silent elimination'. That's the case where the human that wrote the code and the compiler that's interpreting a specification to claim that code can't ever do anything. Rather than transliterate the code as it was written to the machine instructions the programmer probably expected to see were this native machine assembly they'd written, the compiler behaved differently, silently.