<p>Apparently, Go can implement a dead store analysis in the compiler without a CFG. I stumbled upon this example:</p>
<pre><code>func f() string {
 a := &quot;stuff&quot;
 return &quot;&quot;
 return a
}
</code></pre>
<p>It gives an <code>a declared and not used</code> error if the second return is deleted.
Now, what I do not understand is that the common approach would be to check the DFG once the CFG has been created. However, my approach of creating a CFG would result in the second return statement not being part of the CFG as it is not reachable and can, hence, not be inserted anywhere.</p>
<p>Can anyone explain how this is even done and if there are any benefits in doing it like that?</p>

<semantics><static-analysis><control-flow-graph><data-flow-analysis>
How is Go's DSE implemented?
CC BY-SA 4.0
2024-06-21T14:21:13.483Z
I do it by simply checking for occurrences of `a` after its declaration
Seggan
CC BY-SA 4.0
2024-06-21T14:33:08.430Z
And how do you check if that `a` really binds to the definition in question?
feldentm
CC BY-SA 4.0
2024-06-21T15:35:01.783Z
Shadowed variables are renamed, and obviously I only check within `a`'s scope
Seggan
CC BY-SA 4.0
2024-06-21T20:17:05.380Z
I did not understand your question until I read your more detailed blog post (which is not mentioned here) https://medium.com/@feldentm/go-away-go-3-disregarding-compiler-basics-5a7e4d7182ce - There, you claim that your sample code compiles fine as long as it has the second return. However, when I try it I get an `unreachable code` error: https://go.dev/play/p/5MgRt64L0Qm
Eldritch Conundrum
CC BY-SA 4.0
2024-06-21T21:54:24.383Z
Ah, never mind... `unreachable code` is only a warning, and it only errors when removing the unreachable code.
Eldritch Conundrum
CC BY-SA 4.0
2024-06-22T05:58:02.703Z
@EldritchConundrum I also thought at first that the warning is an error because some IDEs present it like that. But it really isn't. I'm not really sure if they simply flag variable declarations while translating the code to some sort of unstructured instruction list. That's my approach after looking at it surprised for several days. But really, are instruction lists still used? I thought that everyone compiles to BB-based CFG from AST directly.
feldentm
CC BY-SA 4.0
2024-06-22T05:59:46.307Z
@EldritchConundrum I didn't link the blog post because it felt too negative.
feldentm
CC BY-SA 4.0
2024-06-22T08:44:39.163Z
@feldentm Isn't it possible to check for uses of `a` in the AST directly?
Eldritch Conundrum
<p>Disclaimer: it's the first time I read the code of the Go compiler, I might have missed many things.</p>
<p>Go's <code>declared and not used</code> error does not come from dead store analysis.
It's working directly on the AST, not on any kind of CFG or DFG.</p>
<p>Unused variables are reported, during the typechecking of statements, in <code>types/stmt.go</code>:</p>
<p><a href="https://github.com/golang/go/blob/44f18706661db8b865719d15a5cfa0515d1a4fca/src/go/types/stmt.go#L68" rel="nofollow noreferrer">https://github.com/golang/go/blob/44f18706661db8b865719d15a5cfa0515d1a4fca/src/go/types/stmt.go#L68</a></p>
<pre class="lang-go prettyprint-override"><code>for name, elem := range scope.elems {
    elem = resolve(name, elem)
    if v, _ := elem.(*Var); v != nil &amp;&amp; !v.used {
        unused = append(unused, v)
    }
}
...
for _, v := range unused {
    check.softErrorf(v, UnusedVar, &quot;declared and not used: %s&quot;, v.name)
}
</code></pre>
<p>That <code>used</code> field  is set to true in a number of places, but most prominently in the <code>ident</code> function of <code>types/typexpr.go</code>, the function that type-checks identifiers:</p>
<p><a href="https://github.com/golang/go/blob/44f18706661db8b865719d15a5cfa0515d1a4fca/src/go/types/typexpr.go#L130" rel="nofollow noreferrer">https://github.com/golang/go/blob/44f18706661db8b865719d15a5cfa0515d1a4fca/src/go/types/typexpr.go#L130</a></p>

CC BY-SA 4.0
2024-06-22T09:25:54.363Z
2024-06-22T09:25:54.363Z
Eldritch Conundrum
CC BY-SA 4.0
2024-06-22T21:42:18.630Z
As to the benefits of doing it like that, that's more difficult to answer. Maybe compiler performance is part of the reason? If there's an UnusedVar error, it's faster to report it and abort compilation as soon as possible, before creating any CFG or DFG.
Eldritch Conundrum
# How is Go's DSE implemented?
Posted by: username_0 on 2024-06-21
Apparently, Go can implement a dead store analysis in the compiler without a CFG. I stumbled upon this example:
func f() string {
 a := "stuff"
 return ""
 return a
}

It gives an a declared and not used error if the second return is deleted.
Now, what I do not understand is that the common approach would be to check the DFG once the CFG has been created. However, my approach of creating a CFG would result in the second return statement not being part of the CFG as it is not reachable and can, hence, not be inserted anywhere.
Can anyone explain how this is even done and if there are any benefits in doing it like that?
**Tags:** semantics static-analysis control-flow-graph data-flow-analysis
> **Comments:**
> **username_1**: I do it by simply checking for occurrences of `a` after its declaration  
> **username_0**: And how do you check if that `a` really binds to the definition in question?  
> **username_1**: Shadowed variables are renamed, and obviously I only check within `a`'s scope  
> **username_2**: I did not understand your question until I read your more detailed blog post (which is not mentioned here) https://medium.com/@feldentm/go-away-go-3-disregarding-compiler-basics-5a7e4d7182ce - There, you claim that your sample code compiles fine as long as it has the second return. However, when I try it I get an `unreachable code` error: https://go.dev/play/p/5MgRt64L0Qm  
> **username_2**: Ah, never mind... `unreachable code` is only a warning, and it only errors when removing the unreachable code.  
> **username_0**: @EldritchConundrum I also thought at first that the warning is an error because some IDEs present it like that. But it really isn't. I'm not really sure if they simply flag variable declarations while translating the code to some sort of unstructured instruction list. That's my approach after looking at it surprised for several days. But really, are instruction lists still used? I thought that everyone compiles to BB-based CFG from AST directly.  
> **username_0**: @EldritchConundrum I didn't link the blog post because it felt too negative.  
> **username_2**: @feldentm Isn't it possible to check for uses of `a` in the AST directly?  
---
## 1 answers
### Answer by username_2 on 2024-06-22. Score: 3 | Accepted answer
Disclaimer: it's the first time I read the code of the Go compiler, I might have missed many things.
Go's declared and not used error does not come from dead store analysis.
It's working directly on the AST, not on any kind of CFG or DFG.
Unused variables are reported, during the typechecking of statements, in types/stmt.go:
https://github.com/golang/go/blob/44f18706661db8b865719d15a5cfa0515d1a4fca/src/go/types/stmt.go#L68
for name, elem := range scope.elems {
    elem = resolve(name, elem)
    if v, _ := elem.(*Var); v != nil && !v.used {
        unused = append(unused, v)
    }
}
...
for _, v := range unused {
    check.softErrorf(v, UnusedVar, "declared and not used: %s", v.name)
}

That used field  is set to true in a number of places, but most prominently in the ident function of types/typexpr.go, the function that type-checks identifiers:
https://github.com/golang/go/blob/44f18706661db8b865719d15a5cfa0515d1a4fca/src/go/types/typexpr.go#L130
> **Comments:**
> **username_2** (2024-06-22): As to the benefits of doing it like that, that's more difficult to answer. Maybe compiler performance is part of the reason? If there's an UnusedVar error, it's faster to report it and abort compilation as soon as possible, before creating any CFG or DFG.  
---
