Thread overview
static analysis: how to test code reachability at compile time
May 21, 2013
Timothee Cour
May 21, 2013
Diggory
May 21, 2013
Timon Gehr
May 21, 2013
 I'd like to have the following tools to help with static analysis & code
coverage:

1) test whether code is reachable or not.

Of course it only works for executables and may have some caveats (eg: goto), but its still useful diagnostic tool.

__traits(isReachable): true when the current context can be reached via at
least one code path starting from main():

----
void fun1(){
//__traits(isReachable) would be false here because even though fun1 is
called by fun2, it can never be called starting from main().
}
void fun2(){fun1;}
void fun3(){} // would also be false, because of static if(temp); with temp
being known to be 0 at compile time.
void fun4(){
return;
//__traits(isReachable) would be false here because all code paths return
above this point.
}
void main(){enum temp=0; static if(temp) fun3; fun4;}
----

When a pointer to a function is taken, we may want to assume by convention that __traits(isReachable) is true.

This would enable for example to make sure a given code is never called. Note, static assert(0) is not the same.

2)
static code call graph: know caller/calling functions for a given function.


3) static code coverage
this would allow us to tell at compile time the code coverage of a module;
it is larger than runtime coverage, but still useful to find dead code.


May 21, 2013
On Tuesday, 21 May 2013 at 21:15:58 UTC, Timothee Cour wrote:
>  I'd like to have the following tools to help with static analysis & code
> coverage:
>
> 1) test whether code is reachable or not.
>
> Of course it only works for executables and may have some caveats (eg:
> goto), but its still useful diagnostic tool.
>
> __traits(isReachable): true when the current context can be reached via at
> least one code path starting from main():
>
> ----
> void fun1(){
> //__traits(isReachable) would be false here because even though fun1 is
> called by fun2, it can never be called starting from main().
> }
> void fun2(){fun1;}
> void fun3(){} // would also be false, because of static if(temp); with temp
> being known to be 0 at compile time.
> void fun4(){
> return;
> //__traits(isReachable) would be false here because all code paths return
> above this point.
> }
> void main(){enum temp=0; static if(temp) fun3; fun4;}
> ----
>
> When a pointer to a function is taken, we may want to assume by convention
> that __traits(isReachable) is true.
>
> This would enable for example to make sure a given code is never called.
> Note, static assert(0) is not the same.
>
> 2)
> static code call graph: know caller/calling functions for a given function.
>
>
> 3) static code coverage
> this would allow us to tell at compile time the code coverage of a module;
> it is larger than runtime coverage, but still useful to find dead code.

It would be very easy to introduce paradoxes if this were possible, simply use a static if to call something only if it is unreachable.
May 21, 2013
On 05/21/2013 11:31 PM, Diggory wrote:
> ...
>
> It would be very easy to introduce paradoxes

This is the case already.

> if this were possible,  simply use a static if to call something only if it is unreachable.

I don't think this would be possible because function-local symbols are not accessible from outside.