<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<div class="moz-cite-prefix">Hello Gabor.<br>
<br>
I'm aware of this issue. As a workaround, I reorder the fields of
imported structure after it is imported. There is no need to
reorder Decls inside other DeclContexts (at least, for analyzer;
but this would make sense if ASTImporter is used together with
Parser).<br>
Thank you also for this awesome repro. When I'll be at least a bit
more free, I'll put the patch on review.<br>
<br>
07.09.2017 17:25, Gábor Horváth пишет:<br>
</div>
<blockquote type="cite"
cite="mid:CAPRL4a2m6pBifbN-8fmWV4rJVePjoCpWwxwKWVxB4HBG3x2kgA@mail.gmail.com">
<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>
</blockquote>
<p><br>
</p>
<pre class="moz-signature" cols="72">--
Best regards,
Aleksei Sidorin,
SRR, Samsung Electronics
</pre>
</body>
</html>