<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2021-05-20T16:41:08+00:00</updated><id>/feed.xml</id><title type="html">Jongy’s blog</title><entry><title type="html">Assert Rewriting - A GCC plugin - part 2</title><link href="/2020/05/15/gcc-assert-introspect-2.html" rel="alternate" type="text/html" title="Assert Rewriting - A GCC plugin - part 2" /><published>2020-05-15T00:00:00+00:00</published><updated>2020-05-15T00:00:00+00:00</updated><id>/2020/05/15/gcc-assert-introspect-2</id><content type="html" xml:base="/2020/05/15/gcc-assert-introspect-2.html">&lt;p&gt;This post continues from where we stopped in &lt;a href=&quot;/2020/04/25/gcc-assert-introspect.html&quot;&gt;part 1&lt;/a&gt; (to recall - last
thing we’ve done was a simple modification of a single node in the AST, and we saw how it reflected in the result)&lt;/p&gt;

&lt;p&gt;Today we’ll build the logic of assert rewriting and also dive deeper into GCC’s API. We’ll try to improve typical
assert messages like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/regular-assert.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;to something nicer:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/patched-assert.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Well, maybe not the entire of it, but the core parts :) The full thing can be found &lt;a href=&quot;https://github.com/Jongy/gcc_assert_introspect&quot;&gt;in the plugin&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;asserts&quot;&gt;Asserts&lt;/h2&gt;

&lt;p&gt;What’s the code in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt;, actually? Is it a macro? A function? Something else?
The answer depends on which C library you use (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; comes from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert.h&lt;/code&gt; which is a part of standard C, distributed
with the C library / libc).
We’ll follow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glibc&lt;/code&gt; which is probably what you have installed. Most desktop Linux distributions use it, so most likely
you have it as well.
&lt;em&gt;See &lt;a href=&quot;https://unix.stackexchange.com/questions/120380/what-c-library-version-does-my-system-use&quot;&gt;this SO&lt;/a&gt; question for instructions on determining the libc your GCC uses.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We can see what’s underneath &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; this way:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;dummy.c
&lt;span class=&quot;c&quot;&gt;#include &amp;lt;assert.h&amp;gt;&lt;/span&gt;
assert&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1 &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gcc &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; dummy.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc -E&lt;/code&gt; doesn’t compile (indeed, this code wouldn’t compile) - it runs the preprocessor (doing all includes
and macros substitution), and dumps the result to the standard output.&lt;/p&gt;

&lt;p&gt;These are the final few lines:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;# 2 &quot;dummy.c&quot; 2
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;# 2 &quot;dummy.c&quot;
&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;# 2 &quot;dummy.c&quot; 3 4
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__extension__&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;# 2 &quot;dummy.c&quot;
&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;# 2 &quot;dummy.c&quot; 3 4
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__assert_fail&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;# 2 &quot;dummy.c&quot;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1 == 1&quot;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;# 2 &quot;dummy.c&quot; 3 4
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;dummy.c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__extension__&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__PRETTY_FUNCTION__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt; marks in the output are hints the preprocessor gives to the compiler - they can be ignored.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__extension__&lt;/code&gt; can also be ignored, it’s &lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gcc/Alternate-Keywords.html&quot;&gt;used to suppress certain warnings&lt;/a&gt;.
Removing them, we remain with:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__assert_fail&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1 == 1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;dummy.c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__PRETTY_FUNCTION__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sizeof&lt;/code&gt; is the first operand of the comma operator, so its result is really unused (it’s also &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;void&lt;/code&gt;ed…).
&lt;a href=&quot;https://sourceware.org/git/?p=glibc.git;a=blob;f=assert/assert.h;h=266ee92e3fb5292b3813cd6607df60b3880dbf5c;hb=HEAD#l99&quot;&gt;A comment&lt;/a&gt; in glibc’s source explains it’s there to trigger warnings possibly masked due to the previous use of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__extension__&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The second operand is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; condition itself: if the condition passes, do nothing; else, call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__assert_fail&lt;/code&gt;,
give it some info (the stringified expression, file name, line number and function name) and it’ll do the dirty work.&lt;/p&gt;

&lt;p&gt;To patch asserts, we first need to identify them in the AST. Let’s see how this code we just saw is represented.&lt;/p&gt;

&lt;h3 id=&quot;asserts-in-the-ast&quot;&gt;Asserts in the AST&lt;/h3&gt;

&lt;p&gt;Write this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dummy.c&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;assert.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remember our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;basic.c&lt;/code&gt; plugin from part 1? We’ll change it to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug_tree(DECL_SAVED_TREE(t))&lt;/code&gt;,
and compile &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dummy.c&lt;/code&gt; with it. &lt;em&gt;Plugin code is &lt;a href=&quot;../../../snippets/gcc-assert-introspect-2/very_basic.c&quot;&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In this post I’ll show shortened versions of AST prints, we already understand their structure so I can omit irrelevant
parts.&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &amp;lt;bind_expr ...
    ...
    body &amp;lt;statement_list ...
        ....
        stmt &amp;lt;bind_expr ...
            body &amp;lt;cond_expr ...
                arg:0 &amp;lt;eq_expr ...
                    arg:0 &amp;lt;parm_decl ... n&amp;gt;
                    arg:1 &amp;lt;integer_cst ... constant 42&amp;gt;
                arg:1 &amp;lt;nop_expr ... type &amp;lt;void_type ...
                    arg:0 &amp;lt;integer_cst ... constant 0&amp;gt;
                arg:2 &amp;lt;call_expr ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;First we see a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIND_EXPR&lt;/code&gt; inside a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATEMENT_LIST&lt;/code&gt;, inside another &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIND_EXPR&lt;/code&gt;!
The outer bind is the function block. It contains a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATEMENT_LIST&lt;/code&gt;, which is a grouping
of multiple, sequential statements. Inside the list there’s another &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIND_EXPR&lt;/code&gt; - this is the block created by
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; (see the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;({ })&lt;/code&gt; wrapping in the generated code?).&lt;/p&gt;

&lt;p&gt;Now, the body of that last bind is the core logic. It is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COND_EXPR&lt;/code&gt;, which represents an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;, or a ternary operator.
It has 3 operands: the condition, an expression to be evaluated if the test passes (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if { ... }&lt;/code&gt; clause) and
an expression to be evaluated if the test fails (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else { ... }&lt;/code&gt; clause).&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The condition is an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EQ_EXPR&lt;/code&gt;, which tests for equality between its 2 operands: our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PARM_DECL&lt;/code&gt; of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;, and the
constant &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;42&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if { ... }&lt;/code&gt; clause is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NOP_EXPR&lt;/code&gt; whose operand is the constant &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NOP_EXPR&lt;/code&gt;s represent conversions which
don’t require code generation (e.g &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int *p; (char*)p;&lt;/code&gt;). This &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NOP_EXPR&lt;/code&gt; has type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;void_type&lt;/code&gt;, so it’s a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;void&lt;/code&gt; cast;
that is, we have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(void)0&lt;/code&gt;. This is the common “empty statement” GCC uses, for when it must put &lt;em&gt;some&lt;/em&gt; statement
(see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_empty_stmt&lt;/code&gt; in GCC, which generates it).&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else { ... }&lt;/code&gt; clause is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL_EXPR&lt;/code&gt; which represents a function call: the call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__assert_fail&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take a deeper look on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL_EXPR&lt;/code&gt; itself:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
  &amp;lt;call_expr ...
      fn &amp;lt;addr_expr ...
          ... arg:0 &amp;lt;function_decl ... __assert_fail&amp;gt;
      arg:0 ...
      arg:1 ...
      arg:2 ...
      arg:3 ...
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It has the called function in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn&lt;/code&gt;, and 4 arguments. The called function is an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ADDR_EXPR&lt;/code&gt;: these nodes
represents the address of an object. The object whose address is used here is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FUNCTION_DECL&lt;/code&gt; of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__assert_fail&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I think that’s enough to write code that “macthes” on AST nodes which are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt;s - that is, the main &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COND_EXPR&lt;/code&gt;
implementing them. The code (which I also use in the plugin) is as follows:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_assert_fail_cond_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_CODE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;COND_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr_else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;COND_EXPR_ELSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TREE_CODE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COND_EXPR_THEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP_EXPR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TREE_CODE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr_else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CALL_EXPR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TREE_CODE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CALL_EXPR_FN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr_else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ADDR_EXPR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TREE_CODE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CALL_EXPR_FN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr_else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FUNCTION_DECL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// IDENTIFIER_POINTER(DECL_NAME(...)) gets the (null-terminated) name string from a declaration.&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;strcmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;__assert_fail&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDENTIFIER_POINTER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DECL_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CALL_EXPR_FN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr_else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;traversal-of-functions-ast&quot;&gt;Traversal of function’s AST&lt;/h2&gt;

&lt;p&gt;We saw that the AST may contain nested &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIND_EXPR&lt;/code&gt;s and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STATEMENT_LIST&lt;/code&gt;s. This calls for some recursive traversal,
displayed in this pseudocode:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;traverse(expr)
    if expr is BIND_EXPR
        expr = bind body of expr

    if expr is STATEMENT_LIST
        for each statement in list
            traverse(statement)
    else
        if is_assert_fail_cond_expr(expr)
            patch assert &amp;lt;-- here the magic happens

traverse(DECL_SAVED_TREE(function))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’ll use the implementation of it in our next example, but I won’t elaborate on it. If you’re interested you can see it the
&lt;a href=&quot;https://github.com/Jongy/gcc_assert_introspect/blob/1cfff7eeaef3caa889b6650dabfd703e71d0f048/plugin.c#L1004&quot;&gt;plugin code&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;assert-rewriting&quot;&gt;Assert Rewriting&lt;/h2&gt;

&lt;p&gt;Let’s start with something simple: generate a nicer “assert failed” message for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert(n == 42)&lt;/code&gt;
we had earlier. Instead of the usual &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Assertion `n == 42' failed&lt;/code&gt;, we’ll aim for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%d == 42&lt;/code&gt;,
where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%d&lt;/code&gt; is the runtime value of the “bad” number.&lt;/p&gt;

&lt;p&gt;We can retain the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COND_EXPR&lt;/code&gt; condition intact, and just replace the call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__assert_fail&lt;/code&gt; with our print.
Basically, for the given assert, we just need to generate the equivalent of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf(&quot;%d == %d&quot;, n, 42)&lt;/code&gt;. Code will
be generated based on input, without hard-coding values, so if the assert changes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n == 43&lt;/code&gt;, our plugin will
generate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf(&quot;%d == %d&quot;, n, 43)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Recall we had the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EQ_EXPR&lt;/code&gt;, being the assert condition.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &amp;lt;eq_expr ..
      arg:0 &amp;lt;parm_decl .. n&amp;gt;
      arg:1 &amp;lt;integer_cst .. constant 42&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If we can construct a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt; call and use these 2 as arguments, that might work.&lt;/p&gt;

&lt;p&gt;How can we construct calls? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_call_expr&lt;/code&gt;! Very obvious name.
&lt;em&gt;Actually, it wasn’t that obvious to me originally… and I found &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_function_call&lt;/code&gt; instead,
which caused me huge problems we’ll discuss later.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Anyway, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_call_expr&lt;/code&gt; accepts 2 + N arguments: the function to be called (e.g &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FUNCTION_DECL&lt;/code&gt; or a function
pointer); N, the number of arguments, and then the arguments themselves.&lt;/p&gt;

&lt;p&gt;How can we get the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FUNCTION_DECL&lt;/code&gt; of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt;? In a quick look for functions named “lookup”, “search”, “identifier”
etc in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree.h&lt;/code&gt; I couldn’t find anything related.
We might not be acquainted with GCC’s codebase, but we know the compiler’s behavior a bit… When does GCC search for
identifiers in the compilation scope? Right before a search fails and it emits &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicit declaration of function&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Search “implicit declaration of function” in GCC’s code (you can narrow down the search directories to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc/{c,c-family}&lt;/code&gt;, where the C frontend code is). All non-comment results are in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c-decl.c&lt;/code&gt;. Actually, all of them
are in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicit_decl_warning&lt;/code&gt;. This function is called in 2 sites from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicitly_declare&lt;/code&gt;, which itself is called
from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_external_ref&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c-typeck.c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_external_ref&lt;/code&gt; gets a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree id&lt;/code&gt; which is an identifier tree - these are common, identifier trees
are e.g the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DECL_NAME&lt;/code&gt; of declarations. It calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lookup_name(id)&lt;/code&gt; then runs some more Objective-C-related stuff which
we don’t care about, and finally checks if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decl&lt;/code&gt; is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL_TREE&lt;/code&gt; - if so, it calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicitly_declare&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So we’ll use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_identifier&lt;/code&gt; to get the identifier node, then use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lookup_name&lt;/code&gt; (which resolves the symbol
according to C scoping rules). Together, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lookup_name(get_identifier(&quot;printf&quot;))&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Last thing we need is to generate the arguments. First argument is a string constant, which we can build
with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_string_literal&lt;/code&gt;. Then, we extract the other arguments from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; condition. Our new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;patch_assert&lt;/code&gt;
function has the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COND_EXPR&lt;/code&gt;. Get the condition with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COND_EXPR_COND&lt;/code&gt; then extract the 2 sides of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EQ_EXPR&lt;/code&gt; with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TREE_OPERAND&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Wrapping them all together, we get:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COND_EXPR_COND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cond_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COND_EXPR_COND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cond_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build_string_literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%d == %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;%d == %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build_call_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lookup_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;printf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// embed it in the expression - replace __assert_fail() call with it&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;COND_EXPR_ELSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cond_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The full code as of this point can be seen &lt;a href=&quot;../../../snippets/gcc-assert-introspect-2/basic_rewrite.c&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Create a dummy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main()&lt;/code&gt; to invoke our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; function with the assert.&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dummy.c&lt;/code&gt; - our code now depends on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt;’s declaration.&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;assert.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Compile and run:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;g++ &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;gcc &lt;span class=&quot;nt&quot;&gt;-print-file-name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;plugin&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/include &lt;span class=&quot;nt&quot;&gt;-fpic&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-shared&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; basic.so basic_rewrite.c
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gcc &lt;span class=&quot;nt&quot;&gt;-fplugin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;./basic.so dummy.c main.c &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; main
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./main
5 &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 42
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Cool! It worked! And if we change the 5 or the 42, we’ll see the values changing accordingly.&lt;/p&gt;

&lt;h3 id=&quot;complex-expressions&quot;&gt;Complex expressions&lt;/h3&gt;

&lt;p&gt;Current prints can be made nicer, but the bigger problem is - we can handle only a single type of expressions.
What if function calls are involved? Logical operators like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;||&lt;/code&gt;? Binary expressions like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Obviously we’d like to follow them and print their operands / sub-expressions as well; It’s a recursive structure
so our code should be recursive as well.&lt;/p&gt;

&lt;p&gt;Here’s the logic I thought of:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Recursively follow both operands of logical &amp;amp; binary operators using depth-first search.&lt;/li&gt;
  &lt;li&gt;When going one level deeper, wrap operand with parentheses.&lt;/li&gt;
  &lt;li&gt;Leaf expressions are collected in a list, eventually passed as arguments to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code for this part, including explaining comments: (&lt;a href=&quot;../../../snippets/gcc-assert-introspect-2/complex_rewrite.c&quot;&gt;full code&lt;/a&gt;)&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// convert the type of 'expr' to text representing its operation, for example &quot;+&quot;&quot; for PLUS_EXPR.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// this list is shortened for brevity.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get_expr_op_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_CODE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EQ_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;==&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NE_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;!=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TRUTH_AND_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TRUTH_ANDIF_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;amp;&amp;amp;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TRUTH_OR_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TRUTH_ORIF_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;||&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PLUS_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MINUS_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;-&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MULT_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TRUNC_DIV_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;default:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// the core logic: recursively calls itself for operands of binary operators.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// wtf? c++? vec&amp;lt;..&amp;gt; *&amp;amp; ??&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create_expression_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;va_gc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_expr_op_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// got a binary operator for this expression?&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// then it's binary! descend into its 2 operands.&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_expression_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_expression_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// wrap them up together&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;snprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;(%s) %s (%s)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xstrdup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// add current expression to arguments list.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// since we descend the tree left-to-right, the order of arguments for printf will match the&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// order in this list.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vec_safe_push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// use %d for everything to keep things simple.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xstrdup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;patch_assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cond_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;va_gc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vec_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_expression_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COND_EXPR_COND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cond_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// format comes first.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vec_safe_insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build_string_literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// UNKNOWN_LOCATION? more on that below.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build_call_expr_loc_vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UNKNOWN_LOCATION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lookup_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;printf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vec_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;COND_EXPR_ELSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cond_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A few things about the code, before we run it.&lt;/p&gt;

&lt;p&gt;First and most important, C++?? Quite surprising. At least, I was surprised…
Although it’s a well-known fact that GCC is written in C++, since the API until now has been quite C-ish, this fact has
slipped my mind.
The first time I &lt;em&gt;realized again&lt;/em&gt; C++ is mixed here was when I searched for call sites of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_string_literal&lt;/code&gt;. Its
definition in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree.c&lt;/code&gt; takes 3 arguments, but all calls to it were passing only 2. Then I looked in its
declaration, and saw it has a default parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree = char_type_node&lt;/code&gt;. AFAIK, C has no default arguments :(&lt;/p&gt;

&lt;p&gt;GCC’s codebase is C++ but many areas of the code are indeed very C-like (making no use of classes and making heavy use of macros).
However, some areas do make use of C++ to its full extents, including heavy use of templates. This sums it up well:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/gcc-internals.jpeg&quot; title=&quot;Thanks @sapir&quot; width=&quot;400&quot; /&gt;&lt;/p&gt;

&lt;p&gt;About the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UNKNOWN_LOCATION&lt;/code&gt;: it is a special constant of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;location_t&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;location_t&lt;/code&gt;s are used widely around GCC
code. These represent the source code location of expressions, declarations etc - many tree types have a location field,
which can be accessed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EXPR_LOCATION&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SET_EXPR_LOCATION&lt;/code&gt;.
These help GCC direct its compilation errors/warnings at the right spot in your source code, and are probably used for
other things as well (e.g generating debug info). You have the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;location_t&lt;/code&gt; of a node in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug_tree&lt;/code&gt; output, it is right before
the closing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt;, for example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dummy.c:4:5 start: dummy.c:4:5 finish: dummy.c:4:5&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UNKNOWN_LOCATION&lt;/code&gt; can substitute any location, but it prevents GCC from relating diagnostics messages
with our source code. &lt;em&gt;In the plugin code, I take the location of the core &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COND_EXPR&lt;/code&gt; once, then use it everywhere.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Okay, let’s try to run (reminder - full code is &lt;a href=&quot;../../../snippets/gcc-assert-introspect-2/complex_rewrite.c&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dummy.c&lt;/code&gt; to:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;assert.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;150&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Compile everything, and run…&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./main
&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;5&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;250&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Awesome!&lt;/p&gt;

&lt;p&gt;By the way, notice anything weird above? The right expression appears to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n == 250&lt;/code&gt;, not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n - 100 == 150&lt;/code&gt; as we
have written. Well, even though our plugin runs quite early (before most optimizations take place), some processing was
already done on the AST, and expressions have changed.&lt;/p&gt;

&lt;h3 id=&quot;more-complexity&quot;&gt;More complexity&lt;/h3&gt;

&lt;p&gt;Any problems with current logic? We’ll explore now.&lt;/p&gt;

&lt;h4 id=&quot;double-evaluation&quot;&gt;Double evaluation&lt;/h4&gt;

&lt;p&gt;Let’s start with this: what if instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;, we embed a function call expression?&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;assert.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;func called!&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;150&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Compile and run:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./main
func called!
func called!
&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;5&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;250&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Twice? But we called it once only! Problem is, we took the expressions from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; and placed them in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt;.
With variables that’s probably okay, but with function calls (i.e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL_EXPR&lt;/code&gt;s) - each appearance of them will lead
to a function call. &lt;em&gt;We can’t just “clone” expressions that have side effects!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the previous post I presented a simple example of “rewriting” an assert in Python. The condition contained a
function call, so we stashed the result in a temporary variable which was used multiple times, instead of calling
the function again.&lt;/p&gt;

&lt;p&gt;So… I was about to develop something similar here. Before diving into it, I spent some time reading the various
documents on expression trees, and was lucky to find the savior: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SAVE_EXPR&lt;/code&gt;. This node does exactly what I needed! A
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SAVE_EXPR&lt;/code&gt; can wrap another expression (which might have side effects), then the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SAVE_EXPR&lt;/code&gt; itself can be used
instead, and it will provide the same value. No matter how many times you clone the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SAVE_EXPR&lt;/code&gt;, the underlying expression
is evaluated at most one time!&lt;/p&gt;

&lt;p&gt;Instead of creating variables for all temporary values, all I needed to do was to wrap all expressions with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SAVE_EXPR&lt;/code&gt;. I won’t go into details on how it’s done here, but can see it &lt;a href=&quot;https://github.com/Jongy/gcc_assert_introspect/blob/1cfff7eeaef3caa889b6650dabfd703e71d0f048/plugin.c#L187&quot;&gt;in the plugin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lesson here: get acquainted with the various types of trees, they might come in handy.&lt;/p&gt;

&lt;h4 id=&quot;short-circuts&quot;&gt;Short-circuts&lt;/h4&gt;

&lt;p&gt;What’ll happen with the following code:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;assert.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stddef.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Well, the assert should fail - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p != NULL&lt;/code&gt; is false. But if we run it…&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./main
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1]    602485 segmentation fault &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;core dumped&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;  ./main
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Da hell. What’s going on here?&lt;/p&gt;

&lt;p&gt;The problem lies within our &lt;em&gt;static&lt;/em&gt; processing of the expression. We create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt; containing all operands of
a complex expression; but in reality, due to short-circuiting, parts of the expression are not evaluated at all:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5 == 4 &amp;amp;&amp;amp; i_am_not_evaluated()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;||&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5 == 5 || i_am_not_evaluated()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Following these basic rules of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;||&lt;/code&gt;, it gets more complex with larger expressions:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;((4 == 3 || evaluated()) &amp;amp;&amp;amp; 1 == 0) &amp;amp;&amp;amp; not_evaluated())&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, obviously the &lt;em&gt;runtime&lt;/em&gt; result of expressions must be taken into account when creating the assert message…&lt;/p&gt;

&lt;h2 id=&quot;runtime-generation&quot;&gt;Runtime generation&lt;/h2&gt;

&lt;p&gt;At this point I made a stop and went to see how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt; does its rewriting (after all, this whole idea came from
it). The core logic of rewriting is in &lt;a href=&quot;https://github.com/pytest-dev/pytest/blob/master/src/_pytest/assertion/rewrite.py&quot;&gt;this file&lt;/a&gt;; it’s very long, so I decided it
will be easier to look in the output it generates instead :) Lucky for us &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt; assert rewriting outputs Python (byte)code
and not assembly.&lt;/p&gt;

&lt;p&gt;Take this simple test file:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyc&lt;/code&gt; files are written for test files; these include the modifications made by assert rewriting, so we just need to
decompile the file generated after one test run.&lt;/p&gt;

&lt;p&gt;Grab &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uncompyle6&lt;/code&gt;, a nice Python decompiler. I recommend using Python 3.6/3.7 because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uncompyle6&lt;/code&gt; failed for me on
3.8.&lt;/p&gt;

&lt;p&gt;Easiest done with Docker:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; python:3.6 /bin/bash
docker&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pytest uncompyle6
docker&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; pytest test.py  &lt;span class=&quot;c&quot;&gt;# test.py is the simple test file from above&lt;/span&gt;
docker&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;uncompyle6 __pycache__/test.cpython-36-pytest-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.pyc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It will output a &lt;em&gt;very&lt;/em&gt; long piece of Python code, compared to how simple and short our assert originally was. It also
makes use of too many obscure character sequences, and Jekyll (the framework rendering this site) wouldn’t agree to render
it, so I put it &lt;a href=&quot;../../../snippets/gcc-assert-introspect-2/decompiled_test.py.txt&quot;&gt;here&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;First thought I had in mind when I saw this was “Too bad Python doesn’t have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SAVE_EXPR&lt;/code&gt;… :)”. It would really
alleviate the use of all temporary variables there.&lt;/p&gt;

&lt;p&gt;Anyway, the logic is roughly: (omitting all irrelevant extra/temporary variables, etc)&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;res1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;res_both&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res_both&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;res2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;res_both&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res_both&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# assert failed!
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# res1 holds the result of the left expr
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# res2 holds the result of the right, only if res1 is True!
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt; rewrote the entire condition, while conforming to short-circuiting rules: it won’t exeucte the right-hand
part of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;and&lt;/code&gt; expression if the left-hand part failed. It also collects information during execution, to be used
if the condition fails eventually.&lt;/p&gt;

&lt;p&gt;We can try doing what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt; does: replace the condition completely, and run it part by part. But this means that if our
logic is broken, we can break the assert condition and its result might come wrong, which is bad. Instead, I decided to add new
code only in the “failed” branch of the condition, so even if my code introduces some errors, they won’t affect the code
in the “happy flow” (i.e, when everything works).
The new code will walk the condition tree in runtime and create the assert message. Since all sub expressions are
wrapped in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SAVE_EXPR&lt;/code&gt;, “re-walking” the condition won’t re-evaluate anything.&lt;/p&gt;

&lt;p&gt;The generated logic for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert(x == 1 &amp;amp;&amp;amp; y == 2);&lt;/code&gt; will look roughly like this C code:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// all good&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// note the &quot;(...) &amp;amp;&amp;amp;&quot;&quot; part, telling us this is the right-hand part of &amp;amp;&amp;amp;.&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(...) &amp;amp;&amp;amp; (%d == 2)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%d == 1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And if we add more complexity? for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert((x == 1 &amp;amp;&amp;amp; y == 2) || z == 3)&lt;/code&gt; it will be:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// all good&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(...) &amp;amp;&amp;amp; (%d == 2)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%d == 1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;) || (%d == 3)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The real logic happens to be a bit more complex :P Mostly because generation has to be recursive (because expressions are
recursive). Following are the relevant parts, commented.
The core function is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make_conditional_expr_repr&lt;/code&gt; which recursively calls itself on the expression tree branches, creating statements
that print the “assert fail” message for each part. The statements are conditional - based on the &lt;em&gt;runtime&lt;/em&gt; value of expressions,
they will print appropriate messages.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I omitted many parts for brevity (i.e, no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SAVE_EXPR&lt;/code&gt;s handling here).&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// builds a COND_EXPR&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;inline&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_build_conditional_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;location_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colon_loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ifexp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op1_original_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op2_original_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#if GCCPLUGIN_VERSION &amp;gt;= 8001 // a32c8316ff282ec
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build_conditional_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colon_loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ifexp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op1_original_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;colon_loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op2_original_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colon_loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#else
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build_conditional_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colon_loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ifexp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op1_original_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;op2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op2_original_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;printf_decl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// builds a printf(format, ...) call with given args&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make_printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;va_gc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build_string_literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vec_safe_insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build_call_expr_loc_vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UNKNOWN_LOCATION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;printf_decl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vec_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build_call_expr_loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UNKNOWN_LOCATION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;printf_decl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make_conditional_expr_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree_code&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TREE_CODE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// for TRUTH_ANDIF_EXPR/TRUTH_AND_EXPR:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// * if left fails, we print only left&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// * if right fails, we print (...) &amp;amp;&amp;amp; right&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// * if both pass, we print nothing&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TRUTH_ANDIF_EXPR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TRUTH_AND_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc_stmt_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// statements that print the left side&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_conditional_expr_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left_stmts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc_stmt_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// statements that print the right side&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(...) &amp;amp;&amp;amp; (&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_conditional_expr_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_stmts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// if &quot;left&quot; condition passes, run &quot;right&quot; statements. else run &quot;left&quot; statements.&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cond&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_build_conditional_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UNKNOWN_LOCATION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;right_stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NULL_TREE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;left_stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NULL_TREE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cond&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// for TRUTH_ORIF_EXPR/TRUTH_OR_EXPR&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// * if left and right fail, we print both&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// * if any pass, we print nothing&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TRUTH_ORIF_EXPR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TRUTH_OR_EXPR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc_stmt_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_conditional_expr_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;) || (&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_conditional_expr_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// if expr passes - print nothing (build_empty_stmt branch).&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// if expr fails - print both&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_build_conditional_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UNKNOWN_LOCATION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;build_empty_stmt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UNKNOWN_LOCATION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NULL_TREE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NULL_TREE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// for others - we always print them - because this code gets called only if the expression it reprs&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// has failed, because the &amp;amp;&amp;amp;/|| code guards it.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc_stmt_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_expr_op_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// if it's a binary expression - print both sides.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;snprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; %s &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_conditional_expr_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_conditional_expr_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// it's a plain value - print it alone.&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;va_gc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;vec_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 1 for the format&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quick_push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;append_to_statement_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stmts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;patch_assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cond_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf_decl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lookup_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;printf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;COND_EXPR_ELSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cond_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;make_conditional_expr_repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COND_EXPR_COND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cond_expr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Full code for this part is &lt;a href=&quot;../../../snippets/gcc-assert-introspect-2/runtime_rewrite.c&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s try it with the previously crashing snippet. Compile and run it again:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./main
0 &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Good. It prints only the left part of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt;. Now change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test(NULL)&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int n = 4; test(&amp;amp;n)&lt;/code&gt; and run again:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./main
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;...&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;4 &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 5&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As expected. And now with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;||&lt;/code&gt;, change the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert(p == NULL || *p == 5)&lt;/code&gt; and run:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./main
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;75904660 &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;4 &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 5&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Awesome :)&lt;/p&gt;

&lt;p&gt;Alright, that’s enough for this post. There are a few more core features/concepts in the plugin, but this post is really long enough
already, kudos for you the readers who have made it here.&lt;/p&gt;

&lt;p&gt;I hope you found this interesting and useful, if you intend to write plugins!&lt;/p&gt;

&lt;p&gt;Also, the plugin itself has been useful to me, and hopefully other developers will make use of it too.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/making-the-compiler-do-it.jpeg&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;a-bit-on-debugging&quot;&gt;A bit on debugging&lt;/h2&gt;

&lt;p&gt;Kidding, I’m not done yet!!&lt;/p&gt;

&lt;p&gt;I’ll finish this post with 2 debugging examples I’d encountered during the development of this plugin. Besides having
somewhat funny conclusion (well, funny in my eyes :), they’re also good teaching for those who want to try working
with GCC’s internals.&lt;/p&gt;

&lt;h3 id=&quot;runtime-compiler-errors&quot;&gt;Runtime compiler errors&lt;/h3&gt;

&lt;p&gt;When writing code, you encounter compilation errors; plugins are no exception. You’ll also get runtime errors.
But in compiler-related code, runtime errors have graver effects than usually expected: your code may seem to run fine, but if it has
any erroneous behavior it might extend beyond the “run time” of your plguin - errors can be introduced into the (legit) code your
plugin helps building!&lt;/p&gt;

&lt;p&gt;I encountered some errors of this type during development. The most annoying one was as follows: compiling a small &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt;
test program worked fine (that is, the assert rewriting code was alright); but when I compiled a bigger project with it, failing
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt;s would SIGSEGV in the rewritten &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; logic.&lt;/p&gt;

&lt;p&gt;How do we investigate this? You don’t have the crashing code… :) &lt;em&gt;Because it’s generated by the plugin, duh. (Actually, I
discovered later that you &lt;strong&gt;can&lt;/strong&gt; get it - we’ll see how soon.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A few words on the plugin, for context: due to some design decision I’d taken, it doesn’t generate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt; calls directly,
but instead generates code that collects the parts into a buffer (using an advancing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sprintf&lt;/code&gt;, like
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pos += sprintf(buf + pos, ...)&lt;/code&gt;) then prints the buffer when done.&lt;/p&gt;

&lt;p&gt;First thing I did was to take a stack trace of the runtime crash with GDB. It was in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_IO_default_xsputn&lt;/code&gt;, called in the chain
from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sprintf&lt;/code&gt;. I followed the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;glibc&lt;/code&gt; code and crossed it with the faulting instruction, to realize that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sprintf&lt;/code&gt;
tried to write to a bad pointer.&lt;/p&gt;

&lt;p&gt;Since it wasn’t deterministic (as I said, it only reproduced on some programs), I felt it has something to do with invalid use
of memory (e.g using uninitialized memory). At this point I just read the generated assembly carefully and found the following:
while the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pos += sprintf(buf + pos, ...)&lt;/code&gt; looks alright, the memory location &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pos&lt;/code&gt; itself is never initialized to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;!
I guess it worked on certain compilations - where, by chance/structure, the relevant stack position where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pos&lt;/code&gt; is was
already zero-initialized.&lt;/p&gt;

&lt;p&gt;Why did it happen? In the plugin code I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DECL_INITIAL&lt;/code&gt; which lets you set the initial value for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DECL&lt;/code&gt;. I took this idea
from some examples I found in the C frontend. Apparently I’ve been using it wrong, and it wasn’t initializing anything…&lt;/p&gt;

&lt;p&gt;Finally I &lt;a href=&quot;https://github.com/Jongy/gcc_assert_introspect/commit/8b96d244bc0f0559b51041fa2ae33cd146a527da&quot;&gt;fixed it&lt;/a&gt; by using a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MODIFY_EXPR&lt;/code&gt; to initialize the variable.&lt;/p&gt;

&lt;p&gt;When I told my friend @sapir about this “bug”, he replied with this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/runtime-compiler-errors.jpeg&quot; width=&quot;400&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Great summary. Also, if someone out there manages to get this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DECL_INITIAL&lt;/code&gt; working as expected, I’d be happy to hear…&lt;/p&gt;

&lt;p&gt;By the way, a useful API that could help me here (had I known it that time) is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print_generic_expr_to_str&lt;/code&gt;: this GCC function
recreates back C code from GENERIC AST! Very cool. It can help you spot problems in your generated/modified AST, because it’s probably
easier to read C code compared to longish &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug_tree&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;However, now that I’m writing this post, I wanted to try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print_generic_expr_to_str&lt;/code&gt; and see if it could spot the problem for me.
But sadly, the C code it generated for the buggy code &lt;em&gt;did&lt;/em&gt; include the initialization of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pos&lt;/code&gt; (it was written as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signed long D.3000 = 0;&lt;/code&gt;, although the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;= 0&lt;/code&gt; wasn’t existing in the generated assembly)
So you should keep your doubt and check the assembly if things go bad :)&lt;/p&gt;

&lt;h3 id=&quot;internal-compiler-error&quot;&gt;internal compiler error&lt;/h3&gt;

&lt;p&gt;Throughout plugin development, you’re gonna get “internal compiler error”s quite a lot. These are GCC’s way to tell you
something got messed up.
Sometimes their cause is clear: it might be a failing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc_assert&lt;/code&gt;, reaching to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc_unreachable&lt;/code&gt; and some other types of runtime
checks.&lt;/p&gt;

&lt;p&gt;And other times they’re like this one:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dummy.c:6:1: internal compiler error: Segmentation fault
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this case they are a nice name to “segmentation fault”, or in other words: your code led to some
memory corruption / invalid access. Now, it might be in your code, and it might be somewhere deep inside GCC’s code
(maybe your use of GCC’s API is incorrect). GCC produces a nice traceback that includes frames of &lt;em&gt;plugin&lt;/em&gt; code, but it doesn’t
include frames of GCC functions.&lt;/p&gt;

&lt;p&gt;One of the crashes I had was in a call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_function_call&lt;/code&gt; (the last frame in the stacktrace GCC gave me was
the line in my plugin calling this function).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;plugin_test.c:26:1: internal compiler error: Segmentation fault
   26 | }
      | ^
0x7faeb3f7a3d4 make_repr_sprintf
    /../gcc_assert_introspect/plugin.c:347
0x7faeb3f7ad57 make_conditional_expr_repr
    /../gcc_assert_introspect/plugin.c:496
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;(As of commit &lt;a href=&quot;https://github.com/Jongy/gcc_assert_introspect/commit/0633d83b924446fb5d9ca36cf405dc7e626551b9&quot;&gt;0633d83b&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So the crash is somewhere in GCC… How can we debug these? What happened, and what was the full GCC stack trace?&lt;/p&gt;

&lt;p&gt;Once again, GDB to the rescue. Now, simply running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdb gcc ...&lt;/code&gt; won’t do because the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc&lt;/code&gt; command is actually a “driver program”
that invokes other commands to do the real work of compiling/linking. The C compiler is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cc1&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc&lt;/code&gt; forks then executes it.
I used &lt;a href=&quot;https://wiki.gentoo.org/wiki/Gcc-ICE-reporting-guide#.5Bbonus.5D_Extract_gcc_backtrace&quot;&gt;this example&lt;/a&gt; which tells GDB to follow the child process after GCC forks.&lt;/p&gt;

&lt;p&gt;Ran with it and got a full stacktrace! Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;backtrace&lt;/code&gt;, top of the stack was:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0x00000000008d12a7 in argument_parser::check_argument_type
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;GCC didn’t have source line information (well, I built this GCC I’ve been using, so blame on me):&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;addr2line &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; ~/opt/gcc-9.1.0/bin/gcc 0x00000000008d12a7
??:0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Bummer :(&lt;/p&gt;

&lt;p&gt;Onwards to the disassembly, then… The faulting code is:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   0x00000000008d1296 &amp;lt;+422&amp;gt;:   jle    0x60f878 &amp;lt;_ZN15argument_parser19check_argument_typeEPK16format_char_infoRK15length_modifierRP9tree_nodeRPKcbRmS8_iSA_SA_jc.part.0.cold+526&amp;gt;
   0x00000000008d129c &amp;lt;+428&amp;gt;:   mov    0x18(%rsp),%rcx
   0x00000000008d12a1 &amp;lt;+433&amp;gt;:   sub    $0x1,%eax
   0x00000000008d12a4 &amp;lt;+436&amp;gt;:   mov    (%rcx),%rdx
=&amp;gt; 0x00000000008d12a7 &amp;lt;+439&amp;gt;:   cmp    0x4(%rdx),%eax
   0x00000000008d12aa &amp;lt;+442&amp;gt;:   jae    0x60f88c &amp;lt;_ZN15argument_parser19check_argument_typeEPK16format_char_infoRK15length_modifierRP9tree_nodeRPKcbRmS8_iSA_SA_jc.part.0.cold+546&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rdx&lt;/code&gt; is dereferenced, but is was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Names are mangled and the function went modifications during LTO (that’s the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.part.0.cold&lt;/code&gt; suffix). So it took me a while to
find the matching C++ code - line numbers would really help. &lt;em&gt;If you build your GCC for development, make sure it has debug
info!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s the faulting code (from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;check_format_types()&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c-format.c&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EXPR_HAS_LOCATION&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cur_param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;param_loc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EXPR_LOCATION&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cur_param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arglocs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/* arg_num is 1-based.  */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gcc_assert&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;types&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg_num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;param_loc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arglocs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;types&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg_num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// &amp;lt;----- CRASH IS HERE&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argloc&lt;/code&gt; is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vec&lt;/code&gt; (from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc/vec.h&lt;/code&gt;). The faulting opcode, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmp 0x4(%rdx), %eax&lt;/code&gt;, is the bounds check before accessing
the element at a given index (the check exists in builds with runtime checks).
Thus &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rdx&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*arglocs&lt;/code&gt;, which is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt;, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arglocs&lt;/code&gt; is not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt;. What?&lt;/p&gt;

&lt;p&gt;Let’s walk the calls - from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_function_call&lt;/code&gt; to this point. So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_function_call&lt;/code&gt; calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c_build_function_call_vec&lt;/code&gt;
with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vNULL&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arg_loc&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vNULL&lt;/code&gt; is the “null” value for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vec&lt;/code&gt;s). We get to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_function_call_vec&lt;/code&gt; which passes it to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;check_function_arguments&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;arg_loc&lt;/code&gt;… And this value reaches our faulting code. Of course &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arglocs&lt;/code&gt; is not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt;! It’s the
address of a parameter - it can never be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt;. But &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*arglocs&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vNULL&lt;/code&gt; and it’s invalid to dereference it.&lt;/p&gt;

&lt;p&gt;I believed this behavior is rather weird; and decided to send &lt;a href=&quot;https://gcc.gnu.org/pipermail/gcc/2020-April/000361.html&quot;&gt;a question&lt;/a&gt; to the GCC mailing list, explaining the
situation and asking if I did anything wrong, or this is a real problem I found here. Didn’t get any reply, so I filed
&lt;a href=&quot;https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94664&quot;&gt;an issue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The issue got a reply pretty fast. One of the GCC developers said it’s not a bug because I wasn’t supposed to use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_function_call&lt;/code&gt; in the first place - it’s only used by the Objective-C/C++ frontends…&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Jongy/gcc_assert_introspect/commit/22d028dab0e96eba0892058edcfdc3b7e3d34689&quot;&gt;My fix&lt;/a&gt; was to create a wrapper for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c_build_function_call_vec&lt;/code&gt; using non-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vNULL&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arg_locs&lt;/code&gt;.
&lt;em&gt;Didn’t use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_call_expr&lt;/code&gt;, see &lt;a href=&quot;https://github.com/Jongy/gcc_assert_introspect/commit/7056cf8efeecf59cce9ee58ff547b2c0270e8bef&quot;&gt;here&lt;/a&gt; for an explanation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Moral of the story? Try to use stuff from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree.h&lt;/code&gt; only. GCC has no explicit distinction between “plugin API”, “C frontend API”
and other pieces of code. You can trust stuff from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree.h&lt;/code&gt; to be valid in virtually all cases; if you use any APIs declared in
other files - make sure they are also used somewhere in the same frontend you’re working with: if writing something that works
with the C frontend (like the plugin described in this article), don’t use functions that aren’t used anywhere in that frontend,
otherwise it’s not unlikely you’ll bump into similar cases.&lt;/p&gt;

&lt;p&gt;It was fun debugging, though :)&lt;/p&gt;

&lt;h2 id=&quot;gcc-plugin-development-resources---part-2&quot;&gt;GCC Plugin Development Resources - part 2&lt;/h2&gt;

&lt;p&gt;We’ll finish, once again, with a collection of some references and tips for plugin developers.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Compile yourself a GCC version with some debug options enabled. Specifically I can vouche for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--enable-checking&lt;/code&gt; of
GCC’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configure&lt;/code&gt;: This enables many types of “tree check” macros which give proper messages before doing some invalid
operation for a given type of node. Helps detecting when you misuse APIs.
e.g it can change an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;internal compiler error: Segmentation fault&lt;/code&gt; to something nicer
like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;internal compiler error: tree check: accessed operand 6 of ne_expr with 2 operands in ...&lt;/code&gt;.
I used &lt;a href=&quot;https://github.com/darrenjs/howto/blob/master/build_scripts/build_gcc_9.sh&quot;&gt;this script&lt;/a&gt; to build, just make sure to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--enable-checking&lt;/code&gt; to the invocation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configure&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;There’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc:&amp;lt;version&amp;gt;&lt;/code&gt; docker image in DockerHub, you can use it to easily test your plugin with different
versions of GCC; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run --rm -it gcc:7 /bin/bash&lt;/code&gt;. (Sadly, these were not built with debugging options ^^)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print_generic_expr_to_str&lt;/code&gt; generates back C code from a given &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GENERIC&lt;/code&gt; expression tree.
Useful during development - you can print it along with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug_tree&lt;/code&gt; to see how certain expressions look.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://dmalcolm.fedorapeople.org/gcc/newbies-guide/debugging.html&quot;&gt;Debugging GCC&lt;/a&gt; with some examples; &lt;a href=&quot;https://wiki.gentoo.org/wiki/Gcc-ICE-reporting-guide#.5Bbonus.5D_Extract_gcc_backtrace&quot;&gt;Debugging hooks on cc1&lt;/a&gt; in GDB.&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><summary type="html">This post continues from where we stopped in part 1 (to recall - last thing we’ve done was a simple modification of a single node in the AST, and we saw how it reflected in the result)</summary></entry><entry><title type="html">Assert Rewriting - A GCC plugin - part 1</title><link href="/2020/04/25/gcc-assert-introspect.html" rel="alternate" type="text/html" title="Assert Rewriting - A GCC plugin - part 1" /><published>2020-04-25T12:31:04+00:00</published><updated>2020-04-25T12:31:04+00:00</updated><id>/2020/04/25/gcc-assert-introspect</id><content type="html" xml:base="/2020/04/25/gcc-assert-introspect.html">&lt;p&gt;This article tells the story of how I got into developing a GCC plugin that rewrites C asserts, in attempt
to mimic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt;’s assert messages. It’s also a beginner’s guide to GCC plugin development.&lt;/p&gt;

&lt;p&gt;The plugin itself is available &lt;a href=&quot;https://github.com/Jongy/gcc_assert_introspect&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;poor-mans-asserts&quot;&gt;Poor man’s asserts&lt;/h2&gt;

&lt;p&gt;A few weeks ago I started working on a small side project in C, nothing too fancy. As with all new
codebases, it was prone to many structural changes, API refactors etc. So I tried to add
as many asserts as possible, and also wrote some basic C tests. &lt;em&gt;When writing lots
of new code, I try to have tests written ASAP, and fill the code with asserts since they help in quickly
catching problems common to a developing codebase (like missed refactors / renames, misused APIs, …).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One thing I dislike about those asserts it that watching them fail usually doesn’t provide you with
all the information necessary to fix the problem. A common assert like:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;will fail with:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;main: main.c:6: main: Assertion `n == 7' failed.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;telling you that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; wasn’t &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;7&lt;/code&gt;, but not telling you &lt;strong&gt;what&lt;/strong&gt; was the value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;, which
might be required to identify the reason of failure.&lt;/p&gt;

&lt;p&gt;The problem gets worse when you have more complex expressions, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;||&lt;/code&gt; or function calls.
So when an assert fails, I usually have to replace it with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf&lt;/code&gt; of all expressions, recompile and rerun the failing
code just so I could know what the problem was.&lt;/p&gt;

&lt;p&gt;Back in that side project, after a session of about 10 “replace-assert-with-printf-then-rerun” changes,
I thought there must be something I could do to improve it.&lt;/p&gt;

&lt;p&gt;Then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt; popped into my mind. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt; is one of the most well-known Python test frameworks, and one of
the features I like in it is that you write your tests logic using plain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt;s, but unlike the standard
Python &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; failure (which raises an empty &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AssertionError&lt;/code&gt;), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt; prints a very elaborated
assert failure message. For example, the following assert:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;will fail with this exception:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;       assert min([1, 2, 3]) - 5 + min(1, 2, 3) == max([5, 6, 5])
E       assert ((1 - 5) + 1) == 6
E        +  where 1 = min([1, 2, 3])
E        +  and   1 = min(1, 2, 3)
E        +  and   6 = max([5, 6, 5])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s very cool. It would have been very useful if I had something similar in C. I decided to try and
build that something, for my C code.&lt;/p&gt;

&lt;h2 id=&quot;adding-introspection-to-asserts&quot;&gt;Adding introspection to asserts&lt;/h2&gt;

&lt;p&gt;I searched online and found &lt;a href=&quot;https://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html&quot;&gt;this&lt;/a&gt; read, which gives a brief introduction on assert rewriting
in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt;. The author (who wrote the feature in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt;) explains how subexpression information
can be displayed by modifying the AST (Abstract Syntax Tree) of your test code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you’re not sure what’s AST, &lt;a href=&quot;https://en.wikipedia.org/wiki/Abstract_syntax_tree#/media/File:Abstract_syntax_tree_for_Euclidean_algorithm.svg&quot;&gt;this&lt;/a&gt; image from Wikipedia will help. It shows the AST of
a simple piece of code, written in its description. You can also take a look in &lt;a href=&quot;https://astexplorer.net/&quot;&gt;AST explorer&lt;/a&gt;
which provides online AST parsing of many languages (doesn’t have C though)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Python, being a dynamic language, allows you to modify the AST of modules during the loading process.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt; uses this to dismantle your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt;s into smaller code pieces that are executed one by one. If
any of them fails, the generated code is ready to print information about the exact point of failure.&lt;/p&gt;

&lt;p&gt;Let’s see a simple, manual “assert rewriting” example. To gain introspection into:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myfunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;we can rewrite it as:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myfunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_tmp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# all good! the assert passed
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;AssertionError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{0} != 12 (myfunc() = {0})&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_tmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;AssertionError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{0} != 8 (n = {0})&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, even for simple expressions it quickly becomes complex. For example, if any of the subexpressions
has side-effects, it must be stored in a temporary variable (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_tmp&lt;/code&gt;) so we don’t invoke
those side-effects multiple times. In the real world it gets even more complicated ;)&lt;/p&gt;

&lt;p&gt;Lucky for us, this conversion is entirely automatic!
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt; takes care of everything, and we get to write human-readable assert expressions.&lt;/p&gt;

&lt;h1 id=&quot;back-to-c&quot;&gt;Back to C&lt;/h1&gt;

&lt;p&gt;C is not a dynamic language. I can’t modify the AST of my program code in runtime. The compiler leaves
you with machine instructions, it’s hard to extract accurate information about the original source code
by messing with them in runtime.&lt;/p&gt;

&lt;p&gt;Test frameworks in C need to provide useful failure message when test asserts fail to help you with
debugging your tests, so they must do something more fancy than plain C &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;What’s common for them is to provide you a set of assert functions, suitable for all comparison
types you may need.
For example, the library &lt;a href=&quot;https://libcheck.github.io/check/&quot;&gt;Check&lt;/a&gt; has the following set of functions/macros (excerpt from
&lt;a href=&quot;https://github.com/libcheck/check/blob/master/src/check.h.in#L576&quot;&gt;src/check.in.h&lt;/a&gt;)&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define     ck_assert_int_eq(X, Y)   _ck_assert_int(X, ==, Y)
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define     ck_assert_int_ne(X, Y)   _ck_assert_int(X, !=, Y)
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define     ck_assert_int_lt(X, Y)   _ck_assert_int(X, &amp;lt;, Y)
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define     ck_assert_int_le(X, Y)   _ck_assert_int(X, &amp;lt;=, Y)
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, you don’t write the expression &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X == Y&lt;/code&gt; but instead use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ck_assert_int_eq&lt;/code&gt; with the arguments
separated. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_ck_assert_int&lt;/code&gt; can use the separated arguments to create a proper assert message:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#define _ck_assert_int(X, OP, Y) do { \
  intmax_t _ck_x = (X); \
  intmax_t _ck_y = (Y); \
  ck_assert_msg(_ck_x OP _ck_y, &quot;Assertion '%s' failed: %s == %jd, %s == %jd&quot;, #X&quot; &quot;#OP&quot; &quot;#Y, #X, _ck_x, #Y, _ck_y); \
} while (0)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This produces useful messages, but the downside is that you have to remember all the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ck_assert_*&lt;/code&gt; functions (the
&lt;a href=&quot;https://libcheck.github.io/check/doc/doxygen/html/check_8h.html&quot;&gt;list&lt;/a&gt; is long), and write unintuitive code instead of a simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt;.
If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ck_assert_int_eq&lt;/code&gt; would accept the expression &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X == Y&lt;/code&gt; instead, it won’t have any introspection on the
expression - it could only operate on the &lt;strong&gt;value&lt;/strong&gt; of it.&lt;/p&gt;

&lt;p&gt;This “problem” isn’t affecting Check only - in C, and in most other compiled languages, you don’t have access to
the information required to parse your code’s own expression trees. You’ll need to be a part of the compilation process in
order to get your hands on the AST. To be a part of the compilation process means, in most compiled languages,
that you are required to be a part of the compiler, or a plugin of it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Actually, Rust is the only language I know that lets &lt;strong&gt;your&lt;/strong&gt; code intervene in it’s own compilation process,
via procedural macros.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update: Reddit comments mentioned &lt;a href=&quot;https://github.com/catchorg/Catch2&quot;&gt;Catch2&lt;/a&gt;, a C++ test framework which (among others) exploits
operator precedence and overloading. Ultimately you have a macro &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REQUIRE(x == 5)&lt;/code&gt; and Catch2 can “parse” this
expression to yeild similar results with respect to what I’m trying to achieve here.
Not exactly AST parsing, but nonetheless it’s very cool so I thought it’s worth to mention here.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We’re in C, so… a GCC plugin it is.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/plugin-vs-macros.jpeg?raw=true&quot; alt=&quot;&quot; title=&quot;And thanks to @sapir for that&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;gcc-plugins-intro&quot;&gt;GCC plugins intro&lt;/h2&gt;

&lt;p&gt;GCC provides &lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gccint/Plugin-API.html#Plugin-API&quot;&gt;an API for plugins&lt;/a&gt;. Plugins are programs built once, then loaded when invoking GCC. They can
modify its behvaior, add new features, etc. More specifically, your plugin can register callbacks which GCC
will call in different steps during compilation, allowing the plugin to mess around with GCC’s internal objects.&lt;/p&gt;

&lt;p&gt;The GCC wiki has a &lt;a href=&quot;https://gcc.gnu.org/wiki/plugins&quot;&gt;short page&lt;/a&gt; with some background on plugins. It also lists some existing
plugins, although the list isn’t so long.
To get the hang of what plugins are capable of, here’s a brief on one of the GCC plugins the Linux kernel uses
for its own build: named &lt;a href=&quot;https://lwn.net/Articles/722293/&quot;&gt;randstruct&lt;/a&gt;, this plugin randomizes the layout of structs during the
kernel build process, so different kernel builds use different layout for their internal structs.
This is an obfuscation, done to help in exploit mitigation. No way you could do that without a plugin -
you’d have to change your code manually.&lt;/p&gt;

&lt;h1 id=&quot;into-gcc&quot;&gt;Into GCC&lt;/h1&gt;

&lt;p&gt;Here’s what I had in mind: I’ll write a plugin that “walks” over functions’ code, identifies calls
to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; and rewrites them with code that’ll do all those nice printings. I didn’t stop to think
how exactly this “code” is gonna work… I didn’t even bother looking in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;py.test&lt;/code&gt;’s implementation,
though I wanted the plugin to produce similar messages.&lt;/p&gt;

&lt;p&gt;So, GCC plugins. I had some experience writing those; a few months ago I wrote &lt;a href=&quot;https://github.com/Jongy/struct_layout&quot;&gt;struct_layout&lt;/a&gt;. That plugin
processes struct definitions as GCC encounters them, then dumps them in a specialized format.&lt;/p&gt;

&lt;p&gt;I started by copying the plugin boilerplate from it. A plugin is basically a shared object which exports a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin_init&lt;/code&gt; function. GCC calls it when the plugin is loaded, and your plugin can register callbacks for
various compilation events using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;register_callback&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Jongy/struct_layout&quot;&gt;struct_layout&lt;/a&gt; registered on the event &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLUGIN_FINISH_DECL&lt;/code&gt;, which is generated &lt;em&gt;after finishing parsing a declaration&lt;/em&gt;.
This time we need an event related to code parsing &amp;amp; AST. A quick look in &lt;a href=&quot;https://github.com/gcc-mirror/gcc/blob/master/gcc/plugin.def&quot;&gt;plugin.def&lt;/a&gt; yields &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLUGIN_PRE_GENERICIZE&lt;/code&gt;
which is documented as &lt;em&gt;allows to see low level AST in C and C++ frontends&lt;/em&gt;. Perfect!&lt;/p&gt;

&lt;p&gt;The required prototype for the callback is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;void my_callback(void *event_data, void *user_data)&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user_data&lt;/code&gt; is a “private data” pointer (we can pass to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;register_callback&lt;/code&gt; and get it here),
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;event_data&lt;/code&gt; is the data itself: a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree&lt;/code&gt; object.&lt;/p&gt;

&lt;h1 id=&quot;gcc-trees&quot;&gt;GCC trees&lt;/h1&gt;

&lt;p&gt;From the &lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gccint/Tree-overview.html&quot;&gt;GCC docs&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;The central data structure used by the internal representation is the tree.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Short enough, but it says a lot. Trees are a very central data structure, literally everything is represented by
a tree object, and those can wield different types and properties. That “internal representation”, made of
trees, creates the AST.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article talks about the GCC internal representation called GENERIC. There’s another internal representation
in GCC, named GIMPLE, but we won’t cover it here.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The AST is composed of multiple nodes; They can represent statements, declarations, types, … you get my point.
We’re interested in reading functions. From my previous work on plugins, I remembered there’s a type of tree for
representing functions: it’s called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FUNCTION_DECL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At this point I didn’t know what’s inside this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FUNCTION_DECL&lt;/code&gt; tree. Plugin development guides are
scarce, but after a bit of searching I found a nice guide giving &lt;a href=&quot;http://icps.u-strasbg.fr/~pop/gcc-ast.html&quot;&gt;concrete examples of AST nodes in GCC&lt;/a&gt;.
I suggest you take a quick stop and read it (it’s short). At least take a look at the fancy diagrams.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Another useful document is &lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gccint/GENERIC.html&quot;&gt;GCC GENERIC docs&lt;/a&gt; where you can find a short
paragraph on many (if not all?) tree types. I keept it open in one tab for the course of developemnt.&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;plugin-basics&quot;&gt;Plugin Basics&lt;/h1&gt;

&lt;p&gt;I think we know enough to start, let’s get some code running. Start by setting up your environment for plugin development.
Some distros require the installation of a “GCC plugin dev” package (e.g Ubuntu), in others you get it in your
standard GCC installation (e.g Arch)&lt;/p&gt;

&lt;p&gt;For Ubuntu:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# You'll need gcc-X-plugin-dev, where X is your GCC major. check it with gcc --version.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# For Ubuntu 18.04 that will be:&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gcc-7-plugin-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s compile the empty plugin skeleton I described above. A minimal file is:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;gcc-plugin.h&amp;gt;
#include &amp;lt;tree.h&amp;gt;
#include &amp;lt;plugin-version.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plugin_is_GPL_compatible&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// must be defined &amp;amp; exported for the plugin to be loaded&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pre_genericize_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plugin_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plugin_name_args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plugin_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plugin_gcc_version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Loaded! compiled for GCC %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gcc_version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;basever&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;register_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plugin_info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PLUGIN_PRE_GENERICIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pre_genericize_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Write it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;basic.c&lt;/code&gt; and build it:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;g++ &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;gcc &lt;span class=&quot;nt&quot;&gt;-print-file-name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;plugin&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/include &lt;span class=&quot;nt&quot;&gt;-fpic&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-shared&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; basic.so basic.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc -print-file-name=plugin&lt;/code&gt; prints the location where plugin headers are installed. We also compile
with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-fpic -shared&lt;/code&gt; to produce a shared library.&lt;/p&gt;

&lt;p&gt;Now we’ll try to load it.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;touch &lt;/span&gt;empty.c
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gcc &lt;span class=&quot;nt&quot;&gt;-fplugin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;./basic.so empty.c &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt;
Loaded! compiled &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;GCC 9.1.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Great. Now what do we do with that tree we have in our callback? It’s time to meet the single-handedly most useful
debugging function you can use while developing for GCC: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug_tree&lt;/code&gt;. It accepts a tree object and dumps it
recursively (to some depth), printing its type, its fields and descendants.&lt;/p&gt;

&lt;p&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#include &amp;lt;print-tree.h&amp;gt;&lt;/code&gt; to the top, and change our callback function to this:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pre_genericize_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;debug_tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’ll write a dummy function and compile it with the plugin active. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-fplugin=/path/to/plugin.so&lt;/code&gt; tells GCC to load
our plugin.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# start by recompiling the plugin&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;g++ &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;gcc &lt;span class=&quot;nt&quot;&gt;-print-file-name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;plugin&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/include &lt;span class=&quot;nt&quot;&gt;-fpic&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-shared&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; basic.so basic.c
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'int dummy(int n) { return n + 5; }'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; dummy.c
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gcc &lt;span class=&quot;nt&quot;&gt;-fplugin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;./basic.so dummy.c &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should see something like::&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &amp;lt;function_decl 0x7f13df35be00 dummy
    type &amp;lt;function_type 0x7f13df263bd0
        type &amp;lt;integer_type 0x7f13df2525e8 int public SI
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is the AST node representing our function. A few words on the format:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Nodes (trees) begin with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; and end with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Node type follows the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt;; Here we have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function_decl&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function_type&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;integer_type&lt;/code&gt;. Those types are themselves
trees.&lt;/li&gt;
  &lt;li&gt;After the node type comes the node object addres in memory. It doesn’t convery much info, but it’s useful
when comparing nodes because it tells you when two nodes are really equal (because they are the same object).&lt;/li&gt;
  &lt;li&gt;After the address comes an optional string describing the node. For declarations, it’s the name (our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function_decl&lt;/code&gt;
is named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dummy&lt;/code&gt;). For types (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;integer_type&lt;/code&gt;) it’s the type name (here &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;The string before an opening &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; is the “name” of the field in the containing node. Here our
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function_decl&lt;/code&gt; has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type&lt;/code&gt; of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function_type&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function_type&lt;/code&gt; has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type&lt;/code&gt; of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;integer_type&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;functions-in-the-ast&quot;&gt;Functions in the AST&lt;/h1&gt;

&lt;p&gt;I don’t see anything in the previous print about the function code, though! One of the diagrams in
&lt;a href=&quot;http://icps.u-strasbg.fr/~pop/gcc-ast.html&quot;&gt;AST representation in GCC&lt;/a&gt; will be of help. It shows functions have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DECL_SAVED_TREE&lt;/code&gt; field, and gives usage
example:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fnBody&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DECL_SAVED_TREE&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fnDecl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The body is a tree itself, of course. So we can alter our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug_tree(t)&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug_tree(DECL_SAVED_TREE(t))&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Recompile the plugin, the recompile &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dummy.c&lt;/code&gt; with the plugin:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &amp;lt;bind_expr 0x7fab614c3a80
    type &amp;lt;void_type 0x7fab6139bf18 void VOID
        align 8 symtab 0 alias set -1 canonical type 0x7fab6139bf18
        pointer_to_this &amp;lt;pointer_type 0x7fab613a30a8&amp;gt;&amp;gt;
    side-effects
    body &amp;lt;return_expr 0x7fab614b1d40 type &amp;lt;void_type 0x7fab6139bf18 void&amp;gt;
        side-effects
        arg 0 &amp;lt;modify_expr 0x7fab614a0b90 type &amp;lt;integer_type 0x7fab6139b5e8 int&amp;gt;
            side-effects arg 0 &amp;lt;result_decl 0x7fab613911e0 D.1794&amp;gt;
            arg 1 &amp;lt;plus_expr 0x7fab614a0b68 type &amp;lt;integer_type 0x7fab6139b5e8 int&amp;gt;
                arg 0 &amp;lt;parm_decl 0x7fab614c4000 n&amp;gt;
                arg 1 &amp;lt;integer_cst 0x7fab613a03f0 constant 5&amp;gt;
                dummy.c:1:29 start: dummy.c:1:27 finish: dummy.c:1:31&amp;gt;
            dummy.c:1:29 start: dummy.c:1:27 finish: dummy.c:1:31&amp;gt;
        dummy.c:1:29 start: dummy.c:1:27 finish: dummy.c:1:31&amp;gt;
    block &amp;lt;block 0x7fab614a97e0 used
        supercontext &amp;lt;function_decl 0x7fab614a4e00 dummy type &amp;lt;function_type 0x7fab613acbd0&amp;gt;
            public static QI file dummy.c line 1 col 5 align 8 initial &amp;lt;block 0x7fab614a97e0&amp;gt; result &amp;lt;result_decl 0x7fab613911e0 D.1794&amp;gt; arguments &amp;lt;parm_decl 0x7fab614c4000 n&amp;gt;
            struct-function 0x7fab614c5000&amp;gt;&amp;gt;
    dummy.c:1:18 start: dummy.c:1:18 finish: dummy.c:1:18&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Lots of prints. Don’t get scared though, read and “parse” it slowly because everything here is logical.
The function body is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bind_expr&lt;/code&gt;. What’s that? Head to the &lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gccint/GENERIC.html&quot;&gt;GENERIC docs&lt;/a&gt; and under Statements -&amp;gt; Blocks
you’ll find a short explanation on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIND_EXPR&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Block scopes and the variables they declare in GENERIC are expressed using the BIND_EXPR code, ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIND_EXPR&lt;/code&gt; is just… Code and variables enclosed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{ }&lt;/code&gt;. Very simple.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug_tree&lt;/code&gt; prints type names like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bind_expr&lt;/code&gt; and field names like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body&lt;/code&gt; in lowercase, but in the source code
these are written in uppercase. From now on, I’ll be using the source notation, uppercase.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We can already see what the body contains, but let’s try getting the inner body tree first. Most tree types have special
macros to access their fields; those can be found in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc/tree.h&lt;/code&gt;. Time to grab a copy of the source!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;When working with the source code of a project, I like having its Git available, so I can look up in the history,
read commit messages, find out when a change was included into the mainline, etc. So I suggest you to clone GCC’s code:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone https://github.com/gcc-mirror/gcc.git&lt;/code&gt;. You can also get the latest version only if you’re hasty:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone --depth 1 https://github.com/gcc-mirror/gcc.git&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;By the way, we already have a local copy of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree.h&lt;/code&gt; and other API headers; We got them when we installed the
plugin dev package. Nonetheless, having the full source code (including the implementation of things) is useful.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc/tree.h&lt;/code&gt; and search for “bind”. If possible, when searching for symbols, use symbolic search in this file since
it’s utterly huge. I use Sublime, so Ctrl+R “bind” led me to&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIND_EXPR_VARS&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIND_EXPR_BODY&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIND_EXPR_BLOCKS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIND_EXPR_BODY&lt;/code&gt; sounds like it. Let’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug_tree&lt;/code&gt; it: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug_tree(BIND_EXPR_BODY(DECL_SAVED_TREE(t)))&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &amp;lt;return_expr 0x7fc48ba6fd40
    type &amp;lt;void_type 0x7fc48b959f18 void VOID
        align 8 symtab 0 alias set -1 canonical type 0x7fc48b959f18
        pointer_to_this &amp;lt;pointer_type 0x7fc48b9610a8&amp;gt;&amp;gt;
    side-effects
    arg 0 &amp;lt;modify_expr 0x7fc48ba5eb90
        type &amp;lt;integer_type 0x7fc48b9595e8 int public SI
            size &amp;lt;integer_cst 0x7fc48b941f18 constant 32&amp;gt;
            unit size &amp;lt;integer_cst 0x7fc48b941f30 constant 4&amp;gt;
            align 32 symtab 0 alias set -1 canonical type 0x7fc48b9595e8 precision 32 min &amp;lt;integer_cst 0x7fc48b941ed0 -2147483648&amp;gt; max &amp;lt;integer_cst 0x7fc48b941ee8 2147483647&amp;gt;
            pointer_to_this &amp;lt;pointer_type 0x7fc48b961a80&amp;gt;&amp;gt;
        side-effects
        arg 0 &amp;lt;result_decl 0x7fc48b94f1e0 D.1794 type &amp;lt;integer_type 0x7fc48b9595e8 int&amp;gt;
            ignored SI file dummy.c line 1 col 5 size &amp;lt;integer_cst 0x7fc48b941f18 32&amp;gt; unit size &amp;lt;integer_cst 0x7fc48b941f30 4&amp;gt;
            align 32 context &amp;lt;function_decl 0x7fc48ba62e00 dummy&amp;gt;&amp;gt;
        arg 1 &amp;lt;plus_expr 0x7fc48ba5eb68 type &amp;lt;integer_type 0x7fc48b9595e8 int&amp;gt;
            arg 0 &amp;lt;parm_decl 0x7fc48ba82000 n&amp;gt;
            arg 1 &amp;lt;integer_cst 0x7fc48b95e3f0 constant 5&amp;gt;
            dummy.c:1:29 start: dummy.c:1:27 finish: dummy.c:1:31&amp;gt;
        dummy.c:1:29 start: dummy.c:1:27 finish: dummy.c:1:31&amp;gt;
    dummy.c:1:29 start: dummy.c:1:27 finish: dummy.c:1:31&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Walk it top down:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RETURN_EXPR&lt;/code&gt; is explained in the GENERIC docs, Statements -&amp;gt; Basic Statements. Its first operand is the value to
return, in our case a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MODIFY_EXPR&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MODIFY_EXPR&lt;/code&gt; is explained under Expressions -&amp;gt; Unary and Binary Expressions: A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MODIFY_EXPR&lt;/code&gt;, simply, is an assignment
(includes assignments like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+=&lt;/code&gt; as well as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;). Here its first operand is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RESULT_DECL&lt;/code&gt;, which is a tree representing the
return value of the current function - a value assigned to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RESULT_DECL&lt;/code&gt; indicates it should be returned.&lt;/li&gt;
  &lt;li&gt;The second operand of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MODIFY_EXPR&lt;/code&gt; is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLUS_EXPR&lt;/code&gt;: a simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; between its 2 operands.&lt;/li&gt;
  &lt;li&gt;The operands to our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PLUS_EXPR&lt;/code&gt; are a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PARM_DECL&lt;/code&gt; (represents a parameter to a function) and an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INTEGER_CST&lt;/code&gt; which
represents integer cosntants. The details displayed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug_tree&lt;/code&gt; show us the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PARM_DECL&lt;/code&gt; is named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;, and the
integer constant is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay, we know how to read and parse out simple AST nodes! Now comes the question - is it possible to overwrite them
during compilation? &lt;em&gt;(Well, ealier I did say it’s possible… but let’s see how)&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;ast-modifications&quot;&gt;AST modifications&lt;/h1&gt;

&lt;p&gt;To replace a node with another one, we’ll need to create a new node first. Functions constructing new trees will begin with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree.h&lt;/code&gt; has plenty of them. Most are not documented in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree.h&lt;/code&gt; itself but instead
in their definition. My suggestion is that you try searching &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree.h&lt;/code&gt; for keywords of what you need, it works
quite well.&lt;/p&gt;

&lt;p&gt;For our modification test - let’s modify the AST to make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dummy&lt;/code&gt; return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n + 10&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n + 5&lt;/code&gt;. So we need to replace
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INTEGER_CST&lt;/code&gt; with another one, holding the value of 10.&lt;/p&gt;

&lt;p&gt;Symbolic searching for “build int” yields &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_int_cst&lt;/code&gt;. It accepts a “type” tree, and a value for the new const.
The “type” may be the tree representing the C type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt;, the C type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;long&lt;/code&gt;, etc. All those common types are declared in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree.h&lt;/code&gt;. We will use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;integer_type_node&lt;/code&gt; for a plain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree.h&lt;/code&gt; we’ll also find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TREE_OPERAND(NODE, I)&lt;/code&gt;, which accesses the I’th operand of a node. This way we can walk
down the expression tree until we get to the node we wish to replace.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pre_genericize_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BIND_EXPR_BODY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DECL_SAVED_TREE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modify&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// replace it! (TREE_OPERAND's result is an lvalue)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;TREE_OPERAND&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;build_int_cst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;integer_type_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Recompile the plugin, recompile &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dummy.c&lt;/code&gt; with the plugin, and write another simple file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dummy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dummy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Build (this time without the plugin):&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gcc main.c dummy.o &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; main  &lt;span class=&quot;c&quot;&gt;# note: use the dummy.o compiled with the plugin, not dummy.c!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And…&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./main
11
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Worked! Hooray.&lt;/p&gt;

&lt;p&gt;You can compile &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dummy.c&lt;/code&gt; again without the plugin to see the difference:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gcc main.c dummy.c &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; main  &lt;span class=&quot;c&quot;&gt;# dummy.c this time&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./main
6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that concludes it for this post.&lt;/p&gt;

&lt;p&gt;I actually intended to focus on the assert rewriting part, but ended up talking about
GCC for the most part. I’m happy it came out this way, though - by this guide I wish to provide smoother entry to
plugin development for everyone. During my career as a developer I have spent many hours reading GCC’s user docs, searching
for the right compiler flag for a task, etc. Gaining insight in the internals, being able to extend C &amp;amp; GCC with features I
couldn’t have earlier - well, it was very nice, and I think every developer should try it sometime :)&lt;/p&gt;

&lt;p&gt;In the &lt;a href=&quot;/2020/05/15/gcc-assert-introspect-2.html&quot;&gt;next part&lt;/a&gt;, we’ll talk about the assert rewriting logic itself, and
how to embed it in the AST via the plugin. We’ll also dive deeper into GCC and GENERIC representation.&lt;/p&gt;

&lt;h2 id=&quot;gcc-plugin-development-resources&quot;&gt;GCC Plugin Development Resources&lt;/h2&gt;

&lt;p&gt;I collected here the references I gave through the article. Many we useful for me during this
project, some I found only afterwards. Anyway, all are useful and thus I put them here together so future plugin
developers can use them.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://icps.u-strasbg.fr/~pop/gcc-ast.html&quot;&gt;AST representation in GCC&lt;/a&gt; - AST in GCC trees.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gccint/GENERIC.html&quot;&gt;GCC GENERIC trees&lt;/a&gt; - the official docs for tree types.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gcc.gnu.org/wiki/GenericAPI&quot;&gt;Understanding Trees&lt;/a&gt; - in GCC wiki, short but contains useful examples.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://rwmj.wordpress.com/2016/02/24/playing-with-gcc-plugins/&quot;&gt;Playing with GCC plugins&lt;/a&gt; - simple plugin that logs structs’ sizes. Insipired me to
try plugins.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://thinkingeek.com/2015/08/16/a-simple-plugin-for-gcc-part-1/&quot;&gt;A simple plugin for GCC&lt;/a&gt; - implements the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;warn_unused_result&lt;/code&gt; attribute
correctly for C++. That guide works with GIMPLE, not with GENERIC as I did here, but some parts are common and
nonetheless it’s an interesting read.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://thinkingeek.com/gcc-tiny/&quot;&gt;GCC tiny&lt;/a&gt;, by the same author of the previous entry - writing a new GCC front end for a simple language.
Based on GENERIC. Very comprehensive.&lt;/li&gt;
  &lt;li&gt;This guide itself :) And its future parts, in days to come…&lt;/li&gt;
&lt;/ol&gt;</content><author><name></name></author><summary type="html">This article tells the story of how I got into developing a GCC plugin that rewrites C asserts, in attempt to mimic py.test’s assert messages. It’s also a beginner’s guide to GCC plugin development.</summary></entry></feed>