<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>