More extensive unused variable checks

Is there any work that is being done on making the unused variable
warning more extensive?

for example:

#include<vector>
void test() {
    std::vector<int> a;
    a.push_back(1);
}
int main() {
    test();
    return 0;
}

Is there any work on saying that test() is a function that will never
do anything, and therefore can be optimized out (and throw a warning
that says that `a` is unused?

I was thinking that perhaps there was a to achieve this with
generalized attributes on the containers and their functions to
determine if an operation was a "load" or "store" type of function,
and then objects that only call one of those two types of instructions
would throw a warning (either unused and can be optimized out, or will
cause undefined behavior).

While I would expect this to be rather straightforward when it comes
to containers (assuming that the possibility of optimizing out
individual entries in the container is excluded), it would be also
interesting to see if a similar idea can be applied to other parts of
the STL.

If there is no work that is being done on this already, is this
something that is
1) useful
2) relatively simple

Is there any work that is being done on making the unused variable
warning more extensive?

for example:

#include<vector>
void test() {
    std::vector<int> a;
    a.push_back(1);
}
int main() {
    test();
    return 0;
}

Is there any work on saying that test() is a function that will never
do anything, and therefore can be optimized out (and throw a warning
that says that `a` is unused?

I was thinking that perhaps there was a to achieve this with
generalized attributes on the containers and their functions to
determine if an operation was a "load" or "store" type of function,
and then objects that only call one of those two types of instructions
would throw a warning (either unused and can be optimized out, or will
cause undefined behavior).

While I would expect this to be rather straightforward when it comes
to containers (assuming that the possibility of optimizing out
individual entries in the container is excluded), it would be also
interesting to see if a similar idea can be applied to other parts of
the STL.

If there is no work that is being done on this already, is this
something that is
1) useful

Yes

2) relatively simple

So far as I know, no. As you say, this would probably require some
attribute scheme to have a reasonable chance of quality. Did you have
some other ideas in mind about how you might overcome this?

- David

I was thinking about an set of attributes for STL containers (just to
make this manageable) that would identify the operations for the
container classes as either read or write (or both, as in the case of
indexers).
Is there a reason not to use attributes for this purpose?

The the same logic that is used in for load/store instructions could
potentially be applied, assuming that the abstractions that the
container provides are not violated.

Special cases:

1. The `insert` method of vector<T> throws a bit of a wrinkle into
matters (though I am confident that list of updated indices should be
relatively easy to maintain).
2. The `data()` member function (where applicable) will probably make
all further attempts an analysis fruitless.
3. The bitset `to_ulong()`,`to_string()`,`any()` and `none()`
functions should mark all bits both written and read
4. The deque<T>, queue<T> and stack<T> have issues similar to vector,
and can be resolved similarly
5. For forward_list<T> and list<T> I am not aware of a reasonably
efficient way of keeping track of dead store, unless no reading
methods are called at all

Notes:

1. Even though swap technically does a read, it should not count as a
read for this purpose
2. If clear occurs before all elements have been read, those elements
that have been stored should be considered dead stores
3. Iterators should probably be considered as reading all data

In short, a totally unused container is very easy to find and deal
with, but doing the individual element dead store elimination is
possible, but harder (at least for some containers).

What about member functions being marked as `const`? Would that be
sufficient indication?

-- Sean Silva

Not really. Const does not enforce no I/O and no modification of
pointer targets. Here is an example:

#include<iostream>
struct test1
{
  int* a;
  test1(int* b){a = b;}
  void mod() const
  {*a=5;}
};
int main()
{
  int q = 2;
  test1 b(&q);
  b.mod();
  std::cout<<q<<std::endl;
  return 0;
}

That is why I believe that attributes will probably be necessary to
solve this issue, though if there is a better way, I would be all for
it.

For types used in conjunction with the standard library, C++11 actually
puts pretty stringent requirements on what a const function can do.
Basically any function marked const that is used in conjunction with the
standard library must be thread-safe (or else you get undefined behavior).
The const member function in your example can easily be seen to race in a
multithreaded context.

See this for more info:
http://channel9.msdn.com/posts/C-and-Beyond-2012-Herb-Sutter-You-dont-know-blank-and-blank

So const may be strong enough for your analyses under the new rules.

-- Sean Silva

Not really. Const does not enforce no I/O and no modification of
pointer targets.

For types used in conjunction with the standard library, C++11 actually puts
pretty stringent requirements on what a const function can do. Basically any
function marked const that is used in conjunction with the standard library
must be thread-safe (or else you get undefined behavior).

I've heard about Herb Sutter talking about this, but I didn't/don't
think it's actually enshrined in the standard, is it? I don't believe
there's any requirement that, say, the elements of a std::vector
implement those semantics even if the vector is used from multiple
threads (with vector providing the "usual thread safety guarantees" of
multiple threads using const operations or one thread exclusively
using non-const operations) - because the const operations of vector
don't actually call anything on the contained elements, for example.

He quotes standard language in that talk. Also, I pretty much trust what
Herb Sutter has to say about these things.

Besides, I like the "thread-safe const/mutable" semantics, so I am biased
towards being willing to believe it :wink:

-- Sean Silva

Thread-safe is nice, but it does not mean that the function has no
side effects (which is the point here).

There is nothing that stops a const function from using mutexes to
ensure synchronous I/O for example.

I have seen the talk that you mention (I belive its
http://channel9.msdn.com/posts/C-and-Beyond-2012-Herb-Sutter-You-dont-know-blank-and-blank),
but I am not sure it is relavant to the topic at hand (though I agree
with its appeal).