D-Programming-Language/dmd — pull request #1886 by jpf91 (2013-04-11 13:24:31+00:00)
Title: [WIP] implement -vgc switch

This is a first try to implement a ```-vgc``` switch. It's supposed to work like ```-vtls``` and print all GC allocations caused by __the language__. It does not help if a external function which allocates is explicitly called in user code.

The output is meant to be easy to parse for IDEs. This way IDEs can hide specific errors (e.g. assert). The output format is
```LOC? vgc[CATEGORY]: (STATEMENT)? msg```
where the following CATEGORIES are used:
```
COV //Code coverage enabled
NEW //User called new (and it's not placement new)
ASSERT_USER //A call to assert. This usually throws, but can be overwritten by user
SWITCH_USER //Called on switch error. This usually throws, but can be overwritten by user
HIDDEN_USER //Called on hidden function error. This usually throws, but can be overwritten by user
CONCAT // a ~ b
ARRAY_LENGTH //array.length = value
APPEND // a~= b
ALITERAL // [1,2,3]
AALITERAL //["a":1]
CLOSURE
```

Some questions where I'd need help:
* I searched for memory allocations by greping for ```RTLSYM_```. Is it possible that there are more allocations?
* I guess there is no easy way to get better file/line information for closures? (I.e. the line which caused the allocation of the closure)
* What about templates? Currently this code also generates warnings for problems in template instances. But this generates lots of output (see https://gist.github.com/jpf91/5363309). Maybe it would be better to only print one error message for the template instance if the template is defined in a different module? What's the best way to implement that?
* What if a runtime hook only allocates if it throws an Error (i.e. invalid usage) or an Exception? Should this still be part of ```-vgc``` output?
* I think implementing it in the frontend is difficult / more error prone. But this way I have to reimplement it for GDC...

Note: This could also be a start to implement a ```-nogc``` parameter which would check a whole module not to use the GC. This is less intrusive than a ```@nogc``` attribute.

```
test-vgc.d(9) vgc[CONCAT]: (a ~ b) causes gc allocation
test-vgc.d(10) vgc[APPEND]: (s ~= "!!!") causes gc allocation
test-vgc.d(13) vgc[CLOSURE]: Using closure causes gc allocation
test-vgc.d(25) vgc[CLOSURE]: Using closure causes gc allocation
test-vgc.d(27) vgc[NEW]: (new A) causes gc allocation
test-vgc.d(28) vgc[NEW]: (new B) causes gc allocation
test-vgc.d(29) vgc[NEW]: (new int) causes gc allocation
test-vgc.d(30) vgc[NEW]: (new int[](42LU)) causes gc allocation
test-vgc.d(32) vgc[ASSERT_USER]: (assert(false,"msg")) may cause gc allocation
test-vgc.d(33) vgc[ASSERT_USER]: (assert(d.length)) may cause gc allocation
test-vgc.d(36) vgc[ARRAY_LENGTH]: (arr.length = 42LU) causes gc allocation
test-vgc.d(40) vgc[ALITERAL]: ([1, 2, 3]) causes gc allocation
test-vgc.d(51) vgc[SWITCH_USER]: calling switch error handler may cause gc allocation
vgc[COV]: Code coverage causes gc allocation
```