<div dir="ltr"><div><div>Hi!<br><br></div>I stumbled upon a serious issue within the AST Importer. First I will walk you through a very synthetic example, then I will try to explain what is happening and finally, I will ask for help if you have a proper solution in mind. <br></div><div><br></div><div><b>The description of the problem</b><br></div><div><br></div><div><b>1. </b>Let's have a simple struct (please ignore the UB in the struct) in <span style="font-family:monospace,monospace">a.cpp</span>:</div><div><span style="font-family:monospace,monospace">struct A {<br>  int b = a + 2;<br>  int a = 5;<br>};</span><br></div><div><br></div><div><b>2.</b> Let's also have an empty <span style="font-family:monospace,monospace">b.cpp</span>.</div><div><b>3.</b> Let's dump the AST of <span style="font-family:monospace,monospace">a.cpp</span>:</div><div><span style="font-family:monospace,monospace">clang -cc1 -emit-pch -o 1.ast a.cpp -std=c++11</span><br></div><div><b>4.</b> Let's merge the dumped AST with the empty file and print the AST:</div><div><span style="font-family:monospace,monospace">clang -cc1 -ast-merge 1.ast -ast-print b.cpp -std=c++11</span><br></div><div><br></div><div>The output is:</div><div><span style="font-family:monospace,monospace">struct A {<br>    int a = 5;<br>    int b = this->a + 2;<br>};</span></div><div><br></div><div>Note that the order of the fields is changed. This is a serious problem since the imported type will not be equivalent to the original one and this can cause various problems during importing non-trivial AST. The same issue can be triggered without having UB in the code, but I wanted to keep the example as small as possible.</div><div><br></div><div>This importing strategy also has further implications. Such as sometimes the ASTImporter ends up checking for equivalence of half done and full definitions. (And they are, of course, not equivalent.)<br></div><div><br></div><div><b>Possible explanation of the problem</b></div><div><br></div><div>During importing a <span style="font-family:monospace,monospace">DeclContext</span> we will add each of the declarations to it. The order of the declarations will be the order in which we add the declarations. In case a declaration is also a definition, we might end up importing the definitions as well before finishing the import of the actual declaration. If a definition refers to a declaration that was not imported yet, we will start importing that declaration. <br></div><div><br></div><div>In the example above the importer starts with importing <span style="font-family:monospace,monospace">A::b</span>. During importing <span style="font-family:monospace,monospace">A::b</span> it will encounter a <span style="font-family:monospace,monospace">DeclRefExpr</span> to <span style="font-family:monospace,monospace">A::a</span>, which is not imported yet. The importer will continue with importing <span style="font-family:monospace,monospace">A::a</span>. After the import of <span style="font-family:monospace,monospace">A::a</span> is finished, it will be added to the <span style="font-family:monospace,monospace">DeclContext</span> before the import of <span style="font-family:monospace,monospace">A::b</span> is finished, thus <span style="font-family:monospace,monospace">A::a</span> end up before <span style="font-family:monospace,monospace">A::b</span> in the imported class.  <br></div><div><br></div><div><b>Possible solutions to the problem</b></div><div><br></div><div>One solution would be to emulate what the parser does, i.e.: first importing only the declarations and after all the declarations are imported continue with the definitions. Unfortunately, I do not see an easy way to implement this logic with the current structure of the ASTImporter, but hopefully, it is only because I am not very familiar with that part of clang. <br></div><div><br></div><div>To circumvent this issue I ended up reordering the declarations within the DeclContext after finishing the import of the definition based on the original DeclContext. This feels like a hacky solution for this problem and also do not solve further implications described above.  <br></div><div><br></div><div><b>Asking for help</b></div><div><br></div><div>What do you think? Did you observe similar anomalies? Do you have any comments or a solution in mind?</div><div><br></div><div>Thanks in advance,</div><div>Gábor Horváth<br></div></div>