www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - We all get nullability wrong sometimes

reply Richard (Rikki) Andrew Cattermole <richard cattermole.co.nz> writes:
Here is a nice little showcase of what the fast DFA engine is 
able to do:

``class IdentExpr``

https://github.com/higgsjs/Higgs/blob/master/source/parser/ast.d#L986

```d
             catchIdent = cast(IdentExpr)parseExpr(input);
             if (catchIdent is null)
                 throw new ParseError("invalid catch identifier", 
catchIdent.pos);
```

https://github.com/higgsjs/Higgs/blob/master/source/parser/parser.d#L462

Anyone notice a slight problem with this code?

While a sound static analyser would be nice, being able to catch 
code like this does mean bugs don't sit around for 10+ years in 
production code, just waiting to give someone a very bad day.

https://github.com/higgsjs/Higgs/issues/219
Jul 09
next sibling parent reply Asadbek <aosindarov gmail.com> writes:
On Thursday, 9 July 2026 at 14:33:54 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 Here is a nice little showcase of what the fast DFA engine is 
 able to do:

 ``class IdentExpr``

 https://github.com/higgsjs/Higgs/blob/master/source/parser/ast.d#L986

 ```d
             catchIdent = cast(IdentExpr)parseExpr(input);
             if (catchIdent is null)
                 throw new ParseError("invalid catch 
 identifier", catchIdent.pos);
 ```

 https://github.com/higgsjs/Higgs/blob/master/source/parser/parser.d#L462

 Anyone notice a slight problem with this code?

 While a sound static analyser would be nice, being able to 
 catch code like this does mean bugs don't sit around for 10+ 
 years in production code, just waiting to give someone a very 
 bad day.

 https://github.com/higgsjs/Higgs/issues/219
I have just checked dmd repository and it appears dmd compiler has custom data flow analysis optimizations. That is really great! Is DFA analysis proving that the `catchIdent` is `null` and therefore catching what would be a runtime error at compile time ?
Jul 09
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 10/07/2026 3:38 AM, Asadbek wrote:
 On Thursday, 9 July 2026 at 14:33:54 UTC, Richard (Rikki) Andrew 
 Cattermole wrote:
 Here is a nice little showcase of what the fast DFA engine is able to do:

 ``class IdentExpr``

 https://github.com/higgsjs/Higgs/blob/master/source/parser/ast.d#L986

 ```d
             catchIdent = cast(IdentExpr)parseExpr(input);
             if (catchIdent is null)
                 throw new ParseError("invalid catch
identifier", 
 catchIdent.pos);
 ```

 https://github.com/higgsjs/Higgs/blob/master/source/parser/parser.d#L462

 Anyone notice a slight problem with this code?

 While a sound static analyser would be nice, being able to catch code 
 like this does mean bugs don't sit around for 10+ years in production 
 code, just waiting to give someone a very bad day.

 https://github.com/higgsjs/Higgs/issues/219
I have just checked dmd repository and it appears dmd compiler has custom data flow analysis optimizations. That is really great! Is DFA analysis proving that the `catchIdent` is `null` and therefore catching what would be a runtime error at compile time ?
I want to clarify something first up, the correct term is Abstract Interpretation, Data Flow Analysis is an application of Abstract Interpretation for backend optimizations. The fast DFA engine isn't actually a DFA, since it has nothing to do with backends, but might do optimizations via setting flags in the future. Why did I call it DFA two years ago? That was because I didn't know that Abstract Interpretation was the correct term, the literature tends to confuse the two quite heavily and I don't think Walter knew of it either. There is no point renaming it today, it would just confusing what with LLM's all about. To answer your question, yes the fast DFA engine there is catching that catchIdent is null, and then erroring. Rather than letting it perform a null dereference at runtime. But please note that this is occurring in my PR for escape analysis that I am currently working on. Principles of Abstract Interpretation is the book I recommend for anyone interested in learning more of the subject. It is written by the original 1970's author who created the term. https://mitpress.mit.edu/9780262044905/principles-of-abstract-interpretation/
Jul 09
parent reply Asadbek <aosindarov gmail.com> writes:
On Thursday, 9 July 2026 at 18:13:14 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 On 10/07/2026 3:38 AM, Asadbek wrote:
 On Thursday, 9 July 2026 at 14:33:54 UTC, Richard (Rikki) 
 Andrew Cattermole wrote:
 [...]
I have just checked dmd repository and it appears dmd compiler has custom data flow analysis optimizations. That is really great! Is DFA analysis proving that the `catchIdent` is `null` and therefore catching what would be a runtime error at compile time ?
I want to clarify something first up, the correct term is Abstract Interpretation, Data Flow Analysis is an application of Abstract Interpretation for backend optimizations. The fast DFA engine isn't actually a DFA, since it has nothing to do with backends, but might do optimizations via setting flags in the future. Why did I call it DFA two years ago? That was because I didn't know that Abstract Interpretation was the correct term, the literature tends to confuse the two quite heavily and I don't think Walter knew of it either. There is no point renaming it today, it would just confusing what with LLM's all about. To answer your question, yes the fast DFA engine there is catching that catchIdent is null, and then erroring. Rather than letting it perform a null dereference at runtime. But please note that this is occurring in my PR for escape analysis that I am currently working on. Principles of Abstract Interpretation is the book I recommend for anyone interested in learning more of the subject. It is written by the original 1970's author who created the term. https://mitpress.mit.edu/9780262044905/principles-of-abstract-interpretation/
Thank you for the suggestion, will definitely check it out. I had lectures about data flow and abstract interpretation as part of program analysis in a compiler course. We only did middle-end optimizations on the LLVM IR not on AST level of our own toy compiler though. I believe dmd does not have its own dedicated IR, do you do the analysis at the AST level ?
Jul 09
next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 10/07/2026 7:35 AM, Asadbek wrote:
 I believe dmd does not have its own dedicated IR, do you do the analysis 
 at the AST level ?
Yes I do. It is syntax directed rather than chaos iteration, and that aligns with AST pretty easily.
Jul 09
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/9/2026 12:35 PM, Asadbek wrote:
 I believe dmd does not have its own dedicated IR,
It does. See the file compiler/src/dmd/backend/el.d
Jul 09
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/9/2026 8:38 AM, Asadbek wrote:
 I have just checked dmd repository and it appears dmd compiler has custom data 
 flow analysis optimizations. That is really great!
It has had DFA since 1985! Most people are shocked to see it in the source code :-)
Jul 09
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
A simpler version of that is:

```d
void foo(int* p)
{
     if (p == null)
         *p = 3;
}
```
which I keep thinking I should implement in the optimizer.

```
void foo()
{
     int* p = null;
     *p = 3;
}
```
already yields from the compiler:

```
Error: null dereference in function _D5test23fooFZv
```
when compiled with -O
Jul 09
parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 10/07/2026 11:09 AM, Walter Bright wrote:
 A simpler version of that is:
 
 ```d
 void foo(int* p)
 {
      if (p == null)
          *p = 3;
 }
 ```
 which I keep thinking I should implement in the optimizer.
That's an easy case. ```d void checkViaObjNullDeref(char cond, int** ptrArg) { int* var; int** ptr = cond ? &var : ptrArg; **ptr = 2; } ``` Try that one, its taken me 4 days to get that to work. Clang can catch this, gcc can't.
Jul 13