<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Tobias Hieta]]></title><description><![CDATA[LLVM developer at Ubisoft.]]></description><link>https://tobias.hieta.se</link><generator>RSS for Node</generator><lastBuildDate>Mon, 08 Jun 2026 07:37:12 GMT</lastBuildDate><atom:link href="https://tobias.hieta.se/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[LLVM 11.0.0 Released - Here are some highlights for C/C++ developers]]></title><description><![CDATA[On Monday 12th of October 2020 LLVM 11.0.0 was released. You can read the release notice from release-manager  Hans Wennborg here.
The release notes are as usual very comprehensive and it can be hard to find the things you really want to know. So I t...]]></description><link>https://tobias.hieta.se/llvm11-release</link><guid isPermaLink="true">https://tobias.hieta.se/llvm11-release</guid><category><![CDATA[C++]]></category><category><![CDATA[C]]></category><dc:creator><![CDATA[Tobias Hieta]]></dc:creator><pubDate>Thu, 15 Oct 2020 11:44:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1602760200985/_zd8vba_f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On Monday 12th of October 2020 LLVM 11.0.0 was released. You can read the release notice from release-manager  <a target="_blank" href="https://twitter.com/hansw2000">Hans Wennborg</a> <a target="_blank" href="https://lists.llvm.org/pipermail/llvm-dev/2020-October/145750.html">here</a>.</p>
<p>The release notes are as usual very comprehensive and it can be hard to find the things you really want to know. So I thought I would go over some of the highlights for this release when it comes to C/C++ developers and toolchain aficionados. This won't cover the internals of LLVM that much - more about using Clang/LLVM as a C/C++ developer.</p>
<h2 id="core-changes">Core changes</h2>
<h3 id="compile-time-performance">Compile-time Performance</h3>
<p>If you have been building larger C++ code bases with Clang you might have noticed that LLVM 10 actually ended up having a pretty big performance regression compared to LLVM 9. This has been rectified in LLVM 11 thanks to the really great work by the Rust community. The details of that speed-up can be found  <a target="_blank" href="https://nikic.github.io/2020/05/10/Make-LLVM-fast-again.html">here</a>.</p>
<p>To test this I did a recompile of the latest <a target="_blank" href="https://github.com/opencv/opencv">OpenCV</a> master in Release configuration on my ThreadRipper 1950X running latest version of Clear Linux:</p>
<p>I ran <code>ninja</code> twice and averaged the number below since filesystem cache can be a thing at times.</p>
<ul>
<li>LLVM 9: 221 seconds</li>
<li>LLVM 10: 231 seconds</li>
<li>LLVM 11: 210 seconds</li>
</ul>
<p>As you see out of the box LLVM 11 is the fastest recent release with a 10% faster compile time compared to LLVM 10 and even 5% faster than 9.</p>
<p>There are also other options that can make LLVM 11 even faster. We will talk about that in the Clang section below.</p>
<h3 id="better-debugging-for-optimized-binaries">Better debugging for optimized binaries</h3>
<p>LLVM can now emit the <code>DW_OP_entry_value</code> instruction for debugging information. This allows the debugger to get more information about local variables that has been removed by the optimizer. This will make debugging better with optimized binaries.</p>
<p>Take this example program:</p>
<pre><code><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">test_function</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> &amp;foo, <span class="hljs-keyword">bool</span> bar)</span>
</span>{
  <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; foo &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
}

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>** argv)</span>
</span>{
  test_function(<span class="hljs-string">"hello world"</span>, <span class="hljs-literal">false</span>);
}
</code></pre><p>When compiled with LLVM like this:
<code>clang++ -o dwp_op_entry_value dwp_op_entry_value.cpp -O3 -g</code></p>
<p>Then run lldb and set a breakpoint in <code>test_function</code>, you can't print what <code>bar</code> was in this case because it was optimized out.</p>
<pre><code>error: Couldn<span class="hljs-string">'t materialize: couldn'</span>t <span class="hljs-keyword">get</span> the <span class="hljs-keyword">value</span> <span class="hljs-keyword">of</span> variable bar: <span class="hljs-keyword">no</span> <span class="hljs-keyword">location</span>, <span class="hljs-keyword">value</span> may have been optimized <span class="hljs-keyword">out</span>
error: errored <span class="hljs-keyword">out</span> <span class="hljs-keyword">in</span> DoExecute, couldn<span class="hljs-string">'t PrepareToExecuteJITExpression</span>
</code></pre><p>The promise with LLVM 11 is that this will not be the case anymore. Unfortunately I was not able to get this to work. Neither in gdb nor lldb. I wonder if the debuggers themselves haven't added support for this at this point. I am sure someone will enlighten me what's missing here.</p>
<h3 id="python-3-migration-has-started">Python 3 migration has started.</h3>
<p>If you are building LLVM/Clang yourself you might want to start to migrate your build machines to Python 3. Python 2 is not deprecated yet - that will happen in LLVM 12, but the build system will now prefer <code>python3</code> over <code>python2</code> in your path.</p>
<h2 id="clang-changes">Clang changes</h2>
<h3 id="fno-common-is-now-the-default"><code>-fno-common</code> is now the default</h3>
<p>When compiling C code with Clang 11 you might get linker errors like this:</p>
<pre><code><span class="hljs-attribute">other</span>.o:(.bss+<span class="hljs-number">0</span>x<span class="hljs-number">0</span>): multiple definition of `hello_global'; main.o:(.bss+<span class="hljs-number">0</span>x<span class="hljs-number">0</span>): first defined here
</code></pre><p>This is because Clang changed so that <code>-fno-common</code> is passed by default (the former default was <code>-fcommon</code>). What does this do? I plugged this into <a target="_blank" href="https://godbolt.org/z/G694e1">Compiler Explorer</a> and you can see that with <code>-fno-common</code> the global variable <code>hello</code> is now a symbol in the assembler.</p>
<p>So if you compile two TU's including a header that defines a global variable you need to make sure to mark it as extern or static.</p>
<p>This change is following a similar change in GCC - the GCC bug tracker has some  <a target="_blank" href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85678">good notes</a> on the change. </p>
<p>Here is a small example:</p>
<p><strong>globals.h</strong></p>
<pre><code><span class="hljs-meta">#<span class="hljs-meta-keyword">pragma</span> once</span>
<span class="hljs-keyword">int</span> hello_global;
</code></pre><p><strong>other.c</strong></p>
<pre><code><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"globals.h"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">test</span><span class="hljs-params">()</span> </span>{
        hello_global = <span class="hljs-number">1</span>;
        <span class="hljs-built_in">fprintf</span>(<span class="hljs-built_in">stderr</span>, <span class="hljs-string">"%d\n"</span>, hello_global);
}
</code></pre><p><strong>main.c</strong></p>
<pre><code><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"globals.h"</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>** argv)</span>
</span>{
  <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre><p>With <code>-fno-common</code> this leads to the duplicate symbol linker error above. Passing <code>-fcommon</code> makes it work or change the following files to this:</p>
<p><strong>globals.h</strong></p>
<pre><code><span class="hljs-meta">#<span class="hljs-meta-keyword">pragma</span> once</span>
<span class="hljs-keyword">extern</span> <span class="hljs-keyword">int</span> hello_global;
</code></pre><p><strong>other.c</strong></p>
<pre><code><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"globals.h"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-keyword">int</span> hello_global;

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">test</span><span class="hljs-params">()</span> </span>{
        hello_global = <span class="hljs-number">1</span>;
        <span class="hljs-built_in">fprintf</span>(<span class="hljs-built_in">stderr</span>, <span class="hljs-string">"%d\n"</span>, hello_global);
}
</code></pre><h3 id="recovery-ast">Recovery AST</h3>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Abstract_syntax_tree">AST</a> of Clang can now include more metadata about errors and will in the future lead to better error handling. Here is the test case used in LLVM to test this feature:</p>
<pre><code><span class="hljs-type">int</span> <span class="hljs-keyword">call</span>(<span class="hljs-type">int</span>);

<span class="hljs-type">void</span> test1(<span class="hljs-type">int</span> s) {
  s = <span class="hljs-keyword">call</span>();
  (<span class="hljs-type">float</span>)<span class="hljs-keyword">call</span>();
}
</code></pre><p>If we inspect the AST with the <code>-dump-ast</code> argument to clang 10:</p>
<pre><code>TranslationUnitDecl <span class="hljs-number">0x11ac778</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt;
|-TypedefDecl <span class="hljs-number">0x11ad050</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt; implicit __int128_t <span class="hljs-string">'__int128'</span>
| `-BuiltinType <span class="hljs-number">0x11acd10</span> <span class="hljs-string">'__int128'</span>
|-TypedefDecl <span class="hljs-number">0x11ad0c0</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt; implicit __uint128_t <span class="hljs-string">'unsigned __int128'</span>
| `-BuiltinType <span class="hljs-number">0x11acd30</span> <span class="hljs-string">'unsigned __int128'</span>
|-TypedefDecl <span class="hljs-number">0x11ad438</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt; implicit __NSConstantString <span class="hljs-string">'__NSConstantString_tag'</span>
| `-RecordType <span class="hljs-number">0x11ad1b0</span> <span class="hljs-string">'__NSConstantString_tag'</span>
|   `-CXXRecord <span class="hljs-number">0x11ad118</span> <span class="hljs-string">'__NSConstantString_tag'</span>
|-TypedefDecl <span class="hljs-number">0x11ad4d0</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt; implicit __builtin_ms_va_list <span class="hljs-string">'char *'</span>
| `-PointerType <span class="hljs-number">0x11ad490</span> <span class="hljs-string">'char *'</span>
|   `-BuiltinType <span class="hljs-number">0x11ac810</span> <span class="hljs-string">'char'</span>
|-TypedefDecl <span class="hljs-number">0x11ea4f8</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt; implicit __builtin_va_list <span class="hljs-string">'__va_list_tag [1]'</span>
| `-ConstantArrayType <span class="hljs-number">0x11ea4a0</span> <span class="hljs-string">'__va_list_tag [1]'</span> <span class="hljs-number">1</span>
|   `-RecordType <span class="hljs-number">0x11ad5c0</span> <span class="hljs-string">'__va_list_tag'</span>
|     `-CXXRecord <span class="hljs-number">0x11ad528</span> <span class="hljs-string">'__va_list_tag'</span>
|-FunctionDecl <span class="hljs-number">0x11ea630</span> &lt;recovery-ast.cpp:<span class="hljs-number">1</span>:<span class="hljs-number">1</span>, col:<span class="hljs-number">13</span>&gt; col:<span class="hljs-number">5</span> <span class="hljs-keyword">call</span> <span class="hljs-string">'int (int)'</span>
| `-ParmVarDecl <span class="hljs-number">0x11ea568</span> &lt;col:<span class="hljs-number">10</span>&gt; col:<span class="hljs-number">13</span> <span class="hljs-string">'int'</span>
`-FunctionDecl <span class="hljs-number">0x11ea7f8</span> &lt;<span class="hljs-type">line</span>:<span class="hljs-number">3</span>:<span class="hljs-number">1</span>, <span class="hljs-type">line</span>:<span class="hljs-number">6</span>:<span class="hljs-number">1</span>&gt; <span class="hljs-type">line</span>:<span class="hljs-number">3</span>:<span class="hljs-number">6</span> test1 <span class="hljs-string">'void (int)'</span>
  |-ParmVarDecl <span class="hljs-number">0x11ea738</span> &lt;col:<span class="hljs-number">12</span>, col:<span class="hljs-number">16</span>&gt; col:<span class="hljs-number">16</span> used s <span class="hljs-string">'int'</span>
  `-CompoundStmt <span class="hljs-number">0x11ea950</span> &lt;col:<span class="hljs-number">19</span>, <span class="hljs-type">line</span>:<span class="hljs-number">6</span>:<span class="hljs-number">1</span>&gt;
</code></pre><p>And then compare it to the AST of Clang 11</p>
<pre><code>TranslationUnitDecl <span class="hljs-number">0x88f5c98</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt;
|-TypedefDecl <span class="hljs-number">0x88f6598</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt; implicit __int128_t <span class="hljs-string">'__int128'</span>
| `-BuiltinType <span class="hljs-number">0x88f6230</span> <span class="hljs-string">'__int128'</span>
|-TypedefDecl <span class="hljs-number">0x88f6608</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt; implicit __uint128_t <span class="hljs-string">'unsigned __int128'</span>
| `-BuiltinType <span class="hljs-number">0x88f6250</span> <span class="hljs-string">'unsigned __int128'</span>
|-TypedefDecl <span class="hljs-number">0x88f6990</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt; implicit __NSConstantString <span class="hljs-string">'__NSConstantString_tag'</span>
| `-RecordType <span class="hljs-number">0x88f66f0</span> <span class="hljs-string">'__NSConstantString_tag'</span>
|   `-CXXRecord <span class="hljs-number">0x88f6660</span> <span class="hljs-string">'__NSConstantString_tag'</span>
|-TypedefDecl <span class="hljs-number">0x88f6a38</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt; implicit __builtin_ms_va_list <span class="hljs-string">'char *'</span>
| `-PointerType <span class="hljs-number">0x88f69f0</span> <span class="hljs-string">'char *'</span>
|   `-BuiltinType <span class="hljs-number">0x88f5d30</span> <span class="hljs-string">'char'</span>
|-TypedefDecl <span class="hljs-number">0x8935540</span> &lt;&lt;invalid sloc&gt;&gt; &lt;invalid sloc&gt; implicit __builtin_va_list <span class="hljs-string">'__va_list_tag [1]'</span>
| `-ConstantArrayType <span class="hljs-number">0x89354e0</span> <span class="hljs-string">'__va_list_tag [1]'</span> <span class="hljs-number">1</span>
|   `-RecordType <span class="hljs-number">0x88f6b20</span> <span class="hljs-string">'__va_list_tag'</span>
|     `-CXXRecord <span class="hljs-number">0x88f6a90</span> <span class="hljs-string">'__va_list_tag'</span>
|-FunctionDecl <span class="hljs-number">0x8935688</span> &lt;recovery-ast.cpp:<span class="hljs-number">1</span>:<span class="hljs-number">1</span>, col:<span class="hljs-number">13</span>&gt; col:<span class="hljs-number">5</span> <span class="hljs-keyword">call</span> <span class="hljs-string">'int (int)'</span>
| `-ParmVarDecl <span class="hljs-number">0x89355b0</span> &lt;col:<span class="hljs-number">10</span>&gt; col:<span class="hljs-number">13</span> <span class="hljs-string">'int'</span>
`-FunctionDecl <span class="hljs-number">0x8935860</span> &lt;<span class="hljs-type">line</span>:<span class="hljs-number">3</span>:<span class="hljs-number">1</span>, <span class="hljs-type">line</span>:<span class="hljs-number">6</span>:<span class="hljs-number">1</span>&gt; <span class="hljs-type">line</span>:<span class="hljs-number">3</span>:<span class="hljs-number">6</span> test1 <span class="hljs-string">'void (int)'</span>
  |-ParmVarDecl <span class="hljs-number">0x8935790</span> &lt;col:<span class="hljs-number">12</span>, col:<span class="hljs-number">16</span>&gt; col:<span class="hljs-number">16</span> used s <span class="hljs-string">'int'</span>
  `-CompoundStmt <span class="hljs-number">0x8935a68</span> &lt;col:<span class="hljs-number">19</span>, <span class="hljs-type">line</span>:<span class="hljs-number">6</span>:<span class="hljs-number">1</span>&gt;
    |-BinaryOperator <span class="hljs-number">0x8935998</span> &lt;<span class="hljs-type">line</span>:<span class="hljs-number">4</span>:<span class="hljs-number">3</span>, col:<span class="hljs-number">12</span>&gt; <span class="hljs-string">'&lt;dependent type&gt;'</span> contains-errors <span class="hljs-string">'='</span>
    | |-DeclRefExpr <span class="hljs-number">0x8935908</span> &lt;col:<span class="hljs-number">3</span>&gt; <span class="hljs-string">'int'</span> lvalue ParmVar <span class="hljs-number">0x8935790</span> <span class="hljs-string">'s'</span> <span class="hljs-string">'int'</span>
    | `-RecoveryExpr <span class="hljs-number">0x8935970</span> &lt;col:<span class="hljs-number">7</span>, col:<span class="hljs-number">12</span>&gt; <span class="hljs-string">'&lt;dependent type&gt;'</span> contains-errors lvalue
    |   `-UnresolvedLookupExpr <span class="hljs-number">0x8935928</span> &lt;col:<span class="hljs-number">7</span>&gt; <span class="hljs-string">'&lt;overloaded function type&gt;'</span> lvalue (ADL) = <span class="hljs-string">'call'</span> <span class="hljs-number">0x8935688</span>
    `-CStyleCastExpr <span class="hljs-number">0x8935a40</span> &lt;<span class="hljs-type">line</span>:<span class="hljs-number">5</span>:<span class="hljs-number">3</span>, col:<span class="hljs-number">15</span>&gt; <span class="hljs-string">'float'</span> contains-errors &lt;Dependent&gt;
      `-RecoveryExpr <span class="hljs-number">0x8935a00</span> &lt;col:<span class="hljs-number">10</span>, col:<span class="hljs-number">15</span>&gt; <span class="hljs-string">'&lt;dependent type&gt;'</span> contains-errors lvalue
        `-UnresolvedLookupExpr <span class="hljs-number">0x89359b8</span> &lt;col:<span class="hljs-number">10</span>&gt; <span class="hljs-string">'&lt;overloaded function type&gt;'</span> lvalue (ADL) = <span class="hljs-string">'call'</span> <span class="hljs-number">0x8935688</span>
</code></pre><p>As you can see the AST now contains even more information around the actual error. It can look back at the declaration of the error etc. This doesn't have that much practical difference yet because it seems like the clang front end doesn't use this data in the actual warning. But in the future it will hopefully lead to better diagnostics for complicated errors especially in C++.</p>
<h3 id="new-warnings">New warnings</h3>
<p>As is normal with every release Clang has added more diagnostics. This time we have two flags that stand out:</p>
<h4 id="wpointer-to-int-cast"><code>-Wpointer-to-int-cast</code></h4>
<p>This warning makes sure you won't cast a pointer to a <code>int</code> when the pointer can contain a bigger value than your int. For example the <code>int</code> type is usually a 32 bit integer while on x86_64 a pointer is 64 bit. So when casting a pointer to a 32 bit int you can lose information due to truncation.</p>
<p>Here is a dumb example that will warn now with clang 11:</p>
<pre><code><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>** argv)</span></span>{
        <span class="hljs-keyword">void</span>* hello = <span class="hljs-literal">NULL</span>;
        <span class="hljs-keyword">int</span> bar = (<span class="hljs-keyword">int</span>)hello;
}
</code></pre><pre><code>pointer_to_int_cast.c:<span class="hljs-number">5</span>:<span class="hljs-number">12</span>: <span class="hljs-built_in">warning</span>: <span class="hljs-keyword">cast</span> <span class="hljs-keyword">to</span> smaller <span class="hljs-type">integer</span> <span class="hljs-keyword">type</span> <span class="hljs-string">'int'</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'void *'</span> [-Wvoid-pointer-<span class="hljs-keyword">to</span>-<span class="hljs-type">int</span>-<span class="hljs-keyword">cast</span>]
        <span class="hljs-type">int</span> bar = (<span class="hljs-type">int</span>)hello;
                  ^~~~~~~~~~
</code></pre><p>Solution is to cast your pointer to a <code>int64_t</code> instead (or you know - don't cast your pointer at all?).</p>
<p><strong>Update</strong>: Arno Lepisk pointed out that <code>intptr_t</code> is the best type to use if you need to cast your pointer to an int.</p>
<h4 id="wuninitialized-const-reference"><code>-Wuninitialized-const-reference</code></h4>
<p>A new warning that will make sure you don't pass a uninitialized const reference to a method. Before we could get warnings from the <code>-Wuninitialized</code> like this:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">foobar</span><span class="hljs-params">(<span class="hljs-keyword">int</span> i)</span> </span>{ }

<span class="hljs-keyword">int</span> i;
foobar(i);
</code></pre><pre><code>uninitialized-const-reference.cpp:<span class="hljs-number">14</span>:<span class="hljs-number">11</span>: <span class="hljs-built_in">warning</span>: variable <span class="hljs-string">'i'</span> <span class="hljs-keyword">is</span> uninitialized <span class="hljs-keyword">when</span> used here [-Wuninitialized]
  foobar(i);
          ^
uninitialized-const-reference.cpp:<span class="hljs-number">13</span>:<span class="hljs-number">8</span>: note: initialize the variable <span class="hljs-string">'i'</span> <span class="hljs-keyword">to</span> silence this <span class="hljs-built_in">warning</span>
  <span class="hljs-type">int</span> i;
       ^
        = <span class="hljs-number">0</span>
</code></pre><p>Which is great - because passing uninitialized variables around can be really bad since it's undefined behavior.</p>
<p>Now this didn't work if <code>foobar</code> took a <code>const&amp; int</code> instead:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">foobar</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-keyword">int</span>&amp; i)</span> </span>{}

<span class="hljs-keyword">int</span> i;
foobar(i);
</code></pre><p>No warning!</p>
<p>But with clang 11 it will say this instead:</p>
<pre><code>uninitialized-<span class="hljs-keyword">const</span>-reference.cpp:<span class="hljs-number">15</span>:<span class="hljs-number">10</span>: warning: variable <span class="hljs-string">'i'</span> <span class="hljs-keyword">is</span> uninitialized <span class="hljs-keyword">when</span> passed <span class="hljs-keyword">as</span> a <span class="hljs-keyword">const</span> reference argument here [-Wuninitialized-<span class="hljs-keyword">const</span>-reference]
  foobar(i);
</code></pre><h3 id="support-for-oz-os-and-og-in-lto">Support for <code>-Oz</code>, <code>-Os</code> and <code>-Og</code> in LTO</h3>
<p>When using <code>-flto=thin/full</code> before clang 11 it didn't like if you used <code>-Os/z/g</code> it just gave an error. This fortunately fixed now and you can pass these optimization flags to the linker as well.</p>
<h3 id="instantiate-templates-in-pch-files">Instantiate templates in PCH files</h3>
<p>This is a nice one! If you use PCH files and use a lot of templates in your codebase this flag can really speed things up. But before we can talk about this flag we need to understand how C++ templates are instatiated.</p>
<p>Let's consider this code:</p>
<pre><code><span class="hljs-keyword">template</span>&lt;<span class="hljs-keyword">class</span> T&gt; T <span class="hljs-keyword">add</span> (T a, T b)
{
  <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-type">int</span> main()
{
  <span class="hljs-type">int</span> i = <span class="hljs-keyword">add</span>&lt;<span class="hljs-type">int</span>&gt;(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>);
  long l = <span class="hljs-keyword">add</span>&lt;long&gt;(<span class="hljs-number">5</span>, <span class="hljs-number">5</span>);
}
</code></pre><p>When the compiler compiles this code it will take the template definition and expand it into all the different versions needed. This can be seen by going back to the AST again:</p>
<p><code>clang++ -Xclang -ast-print -fsyntax-only templates.cpp</code></p>
<pre><code><span class="hljs-keyword">template</span> &lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">T</span>&gt; <span class="hljs-title">T</span> <span class="hljs-title">add</span>(<span class="hljs-title">T</span> <span class="hljs-title">a</span>, <span class="hljs-title">T</span> <span class="hljs-title">b</span>) {</span>
    <span class="hljs-keyword">return</span> a + b;
}
<span class="hljs-keyword">template</span>&lt;&gt; <span class="hljs-keyword">int</span> add&lt;<span class="hljs-keyword">int</span>&gt;(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b) {
    <span class="hljs-keyword">return</span> a + b;
}
<span class="hljs-keyword">template</span>&lt;&gt; <span class="hljs-keyword">long</span> add&lt;<span class="hljs-keyword">long</span>&gt;(<span class="hljs-keyword">long</span> a, <span class="hljs-keyword">long</span> b) {
    <span class="hljs-keyword">return</span> a + b;
}
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">int</span> i = add&lt;<span class="hljs-keyword">int</span>&gt;(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>);
    <span class="hljs-keyword">long</span> l = add&lt;<span class="hljs-keyword">long</span>&gt;(<span class="hljs-number">5</span>, <span class="hljs-number">5</span>);
}
</code></pre><p>Now you see that the compiler added versions of the function with <code>long</code> and <code>int</code> arguments.</p>
<p>Templates in C++ are a great way to generate a lot of similar functions, but they are also very expensive for the compiler to compile since it has to compile them for each instance. The standard library uses a lot of templates so just including some simple headers will easily add a lot of template instatiations.</p>
<p>In Clang 11 we will get a new option to reduce the time that's spent on creating all these instances with the help of the precompiled header. If you pass <code>-fpch-instantiate-templates</code> to Clang when you create the precompiled header the template instantiation will happen directly and stored in the PCH instead of happening once per translation unit.</p>
<p>If your project is using CMake it's actually really simple to turn this on and it has no real downsides. You can either upgrade to CMake 3.19 which will turn this on by default if you using Clang 11 or newer. See the documentation on <a target="_blank" href="https://cmake.org/cmake/help/v3.19/prop_tgt/PCH_INSTANTIATE_TEMPLATES.html#prop_tgt:PCH_INSTANTIATE_TEMPLATES">PCH_INSTANTIATE_TEMPLATES</a></p>
<p>If you are using older versions of CMake you can do this:</p>
<pre><code><span class="hljs-selector-tag">list</span>(APPEND CMAKE_CXX_COMPILE_OPTIONS_CREATE_PCH -fpch-instantiate-templates)
</code></pre><p>In our code base this gave us around a 15% compile time boost. So I highly recommend you look into enabling this.</p>
<h3 id="template-codegen-in-the-pch">Template codegen in the PCH</h3>
<p>There is yet another option to do codegen in the PCH as well. That means that the template instances and other things are compiled into a object in the PCH phase and then you have to link to this in the link phase.</p>
<p>This is a bit more complicated to integrate into your build system, but can once again give a boost to compile speed.</p>
<p>There are <a target="_blank" href="https://gitlab.kitware.com/cmake/cmake/-/issues/21133#note_823725">discussions</a> on the CMake bug tracker on how to integrate this. That's a good place to find information on how to enable this until we get upstream CMake support.</p>
<h3 id="whole-program-de-virtualization">Whole program de-virtualization</h3>
<p>Added in Clang 11 is a feature that is meant to be used together with <a target="_blank" href="https://llvm.org/docs/LinkTimeOptimization.html">LTO</a>. The flag is called <code>-fwhole-program-vtables</code> and will try to de-virtualize your whole program instead of a per translation unit basis.</p>
<p>This is important because of how much more efficient de-virtualized code is. You can see an example of de-virtualization on <a target="_blank" href="https://godbolt.org/z/553Wqs">compiler explorer</a>, just compare the bottom assembler output (de-virtualized) with the top one. And read more about de-virtualization in this <a target="_blank" href="https://marcofoco.com/the-power-of-devirtualization/">article</a> by Marco Foco.</p>
<p>What this flag does in conjuction with <code>-flto=thin/full</code> is that it allows the compiler to de-virtualize even more functions across the whole application instead of just when compiling a single TU.</p>
<p>As far as I know there are no downsides to using this but only upsides.</p>
<p><strong>Update:</strong> Hans pointed out on <a target="_blank" href="https://twitter.com/hansw2000/status/1316717283482447873">twitter</a> that this flag isn't actually new. Instead how it interact with <a target="_blank" href="https://t.co/ZiiBJX3uv4?amp=1">LTO Visibility</a> is new.</p>
<h2 id="many-many-other-changes">Many many other changes</h2>
<p>There are so many more changes here that I can't go through them all, but I wanted to highlight a few very quickly:</p>
<ul>
<li>The LLVM linker LLD saw huge updates during the development cycle and I think it can be considered to be production safe at this point. <a target="_blank" href="https://releases.llvm.org/11.0.0/tools/lld/docs/ReleaseNotes.html">LLD Release Notes</a></li>
<li>Clangd also saw a lot of changes and it seems a lot more usable and robust now. <a target="_blank" href="https://releases.llvm.org/11.0.0/tools/clang/tools/extra/docs/ReleaseNotes.html">clang-tools-extra Release Notes</a></li>
<li>According to the release notes for <code>libc++</code> nothing much happened during this cycle. Basically only adding <code>&lt;numbers&gt;</code> from C++20. But looking at the <a target="_blank" href="https://github.com/llvm/llvm-project/commits/release/11.x/libcxx">commit log</a> there seems to be a lot of changes that was not documented.</li>
</ul>
<p>Hope you enjoyed this deeper dive into LLVM 11. Let me know if this is something I should continue to do for future releases, and if there is something you would like to see a even deeper dive into.</p>
<p>Thanks to <a target="_blank" href="https://twitter.com/szeleitamas">Tamàs Szelei</a>,  <a target="_blank" href="https://twitter.com/bjoreman">Fredrik Björeman</a> and <a target="_blank" href="https://twitter.com/bjorn_fahller">Björn Fahller</a> for proof-reading this article!</p>
<p>Thanks to <a target="_blank" href="https://twitter.com/alexjprice">Alex Stevenson-Price</a> for helping me with pixels!</p>
]]></content:encoded></item></channel></rss>