<div dir="ltr">Hi Douglas,<div><br></div><div>Looked into that yesterday, there's a mismatch between windows and linux paths in the output.</div><div>I'll come up with a fix today.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jul 24, 2017 at 9:08 PM, Yung, Douglas <span dir="ltr"><<a href="mailto:douglas.yung@sony.com" target="_blank">douglas.yung@sony.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Ilya,<br>
<br>
Your change seems to be causing the test 'clangd/definitions.test' to fail on the PS4 Windows bot. Can you take a look?<br>
<br>
<a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/11222" rel="noreferrer" target="_blank">http://lab.llvm.org:8011/<wbr>builders/llvm-clang-lld-x86_<wbr>64-scei-ps4-windows10pro-fast/<wbr>builds/11222</a><br>
<br>
FAIL: Clang Tools :: clangd/definitions.test (11935 of 34225)<br>
******************** TEST 'Clang Tools :: clangd/definitions.test' FAILED ********************<br>
Script:<br>
--<br>
clangd -run-synchronously < C:\ps4-buildslave2\llvm-clang-<wbr>lld-x86_64-scei-ps4-<wbr>windows10pro-fast\llvm.src\<wbr>tools\clang\tools\extra\test\<wbr>clangd\definitions.test | FileCheck C:\ps4-buildslave2\llvm-clang-<wbr>lld-x86_64-scei-ps4-<wbr>windows10pro-fast\llvm.src\<wbr>tools\clang\tools\extra\test\<wbr>clangd\definitions.test<br>
--<br>
Exit Code: 1<br>
<br>
Command Output (stdout):<br>
--<br>
$ "clangd" "-run-synchronously"<br>
# command stderr:<br>
<-- {"jsonrpc":"2.0","id":0,"<wbr>method":"initialize","params":<wbr>{"processId":123,"rootPath":"<wbr>clangd","capabilities":{},"<wbr>trace":"off"}}<br>
<br>
--> {"jsonrpc":"2.0","id":0,"<wbr>result":{"capabilities":{<br>
<br>
          "textDocumentSync": 1,<br>
<br>
          "documentFormattingProvider": true,<br>
<br>
          "<wbr>documentRangeFormattingProvide<wbr>r": true,<br>
<br>
          "<wbr>documentOnTypeFormattingProvid<wbr>er": {"firstTriggerCharacter":"}","<wbr>moreTriggerCharacter":[]},<br>
<br>
          "codeActionProvider": true,<br>
<br>
          "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">"]},<br>
<br>
          "definitionProvider": true<br>
<br>
        }}}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didOpen","params"<wbr>:{"textDocument":{"uri":"file:<wbr>///main.cpp","languageId":"<wbr>cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[{"range":{"<wbr>start": {"line": 2, "character": 1}, "end": {"line": 2, "character": 1}},"severity":2,"message":"<wbr>expression result unused"}]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>2,"character":0}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>2,"character":1}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>2},"contentChanges":[{"text":"<wbr>struct Foo {\nint x;\n};\nint main() {\n  Foo bar = { x : 1 };\n}\n"}]}}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[{"range":{"<wbr>start": {"line": 4, "character": 15}, "end": {"line": 4, "character": 15}},"severity":2,"message":"<wbr>use of GNU old-style field designator extension"}]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>4,"character":14}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>3},"contentChanges":[{"text":"<wbr>struct Foo {\nint x;\n};\nint main() {\n  Foo baz = { .x = 2 };\n}\n"}]}}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>4,"character":15}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>4},"contentChanges":[{"text":"<wbr>int main() {\n   main();\n   return 0;\n}"}]}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>1,"character":3}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 0}, "end": {"line": 3, "character": 1}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>5},"contentChanges":[{"text":"<wbr>struct Foo {\n};\nint main() {\n   Foo bar;\n   return 0;\n}\n"}]}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>3,"character":3}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 0}, "end": {"line": 1, "character": 1}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>5},"contentChanges":[{"text":"<wbr>namespace n1 {\nstruct Foo {\n};\n}\nint main() {\n   n1::Foo bar;\n   return 0;\n}\n"}]}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>5,"character":4}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 0}, "end": {"line": 3, "character": 1}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>6},"contentChanges":[{"text":"<wbr>struct Foo {\n  int x;\n};\nint main() {\n   Foo bar;\n   bar.x;\n}\n"}]}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[{"range":{"<wbr>start": {"line": 5, "character": 8}, "end": {"line": 5, "character": 8}},"severity":2,"message":"<wbr>expression result unused"}]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>5,"character":7}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 2}, "end": {"line": 1, "character": 7}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>7},"contentChanges":[{"text":"<wbr>struct Foo {\n  void x();\n};\nint main() {\n   Foo bar;\n   bar.x();\n}\n"}]}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>5,"character":7}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 1, "character": 2}, "end": {"line": 1, "character": 10}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>7},"contentChanges":[{"text":"<wbr>struct Foo {\n};\ntypedef Foo TypedefFoo;\nint main() {\n   TypedefFoo bar;\n   return 0;\n}\n"}]}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>4,"character":10}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 2, "character": 0}, "end": {"line": 2, "character": 22}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>7},"contentChanges":[{"text":"<wbr>template <typename MyTemplateParam>\nvoid foo() {\n MyTemplateParam a;\n}\nint main() {\n   return 0;\n}\n"}]}}<br>
<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>2,"character":13}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>7},"contentChanges":[{"text":"<wbr>namespace ns {\nstruct Foo {\nstatic void bar() {}\n};\n}\nint main() {\n   ns::Foo::bar();\n   return 0;\n}\n"}]}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>6,"character":4}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 0}, "end": {"line": 4, "character": 1}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>7},"contentChanges":[{"text":"<wbr>namespace ns {\nstruct Foo {\n  int field;\n  Foo(int param) : field(param) {}\n};\n}\nint main() {\n   return 0;\n}\n"}]}}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>3,"character":21}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 2, "character": 2}, "end": {"line": 2, "character": 11}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>7},"contentChanges":[{"text":"<wbr>#define MY_MACRO 0\nint main() {\n  return MY_MACRO;\n}\n"}]}}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>2,"character":9}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///C:/main.cpp", "range": {"start": {"line": 0, "character": 8}, "end": {"line": 0, "character": 18}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","method":"<wbr>textDocument/didChange","<wbr>params":{"textDocument":{"uri"<wbr>:"file:///main.cpp","version":<wbr>7},"contentChanges":[{"text":"<wbr>#define FOO 1\nint a = FOO;\n#define FOO 2\nint b = FOO;\n#undef FOO\n"}]}}<br>
<br>
--> {"jsonrpc":"2.0","method":"<wbr>textDocument/<wbr>publishDiagnostics","params":{<wbr>"uri":"file:///main.cpp","<wbr>diagnostics":[{"range":{"<wbr>start": {"line": 2, "character": 9}, "end": {"line": 2, "character": 9}},"severity":2,"message":"'<wbr>FOO' macro redefined"}]}}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>1,"character":8}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///C:/main.cpp", "range": {"start": {"line": 0, "character": 8}, "end": {"line": 0, "character": 13}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>3,"character":8}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 2, "character": 8}, "end": {"line": 2, "character": 13}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","id":1,"<wbr>method":"textDocument/<wbr>definition","params":{"<wbr>textDocument":{"uri":"file:///<wbr>main.cpp"},"position":{"line":<wbr>4,"character":7}}}<br>
<br>
--> {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 2, "character": 8}, "end": {"line": 2, "character": 13}}}]}<br>
<br>
<-- {"jsonrpc":"2.0","id":3,"<wbr>method":"shutdown"}<br>
<br>
<br>
$ "FileCheck" "C:\ps4-buildslave2\llvm-<wbr>clang-lld-x86_64-scei-ps4-<wbr>windows10pro-fast\llvm.src\<wbr>tools\clang\tools\extra\test\<wbr>clangd\definitions.test"<br>
# command stderr:<br>
C:\ps4-buildslave2\llvm-clang-<wbr>lld-x86_64-scei-ps4-<wbr>windows10pro-fast\llvm.src\<wbr>tools\clang\tools\extra\test\<wbr>clangd\definitions.test:142:<wbr>10: error: expected string not found in input<br>
<br>
# CHECK: {"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 8}, "end": {"line": 0, "character": 18}}}]}<br>
<br>
         ^<br>
<br>
<stdin>:61:150: note: scanning from here<br>
<br>
{"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 2, "character": 2}, "end": {"line": 2, "character": 11}}}]}Content-Length: 113<br>
<br>
                                                                                                                                                     ^<br>
<br>
<stdin>:71:1: note: possible intended match here<br>
<br>
{"jsonrpc":"2.0","id":1,"<wbr>result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 2, "character": 8}, "end": {"line": 2, "character": 13}}}]}Content-Length: 149<br>
<br>
^<br>
<br>
<br>
error: command failed with exit status: 1<br>
<br>
--<br>
<br>
********************<br>
<div><div class="h5"><br>
> -----Original Message-----<br>
> From: cfe-commits [mailto:<a href="mailto:cfe-commits-bounces@lists.llvm.org">cfe-commits-bounces@<wbr>lists.llvm.org</a>] On Behalf Of<br>
> Ilya Biryukov via cfe-commits<br>
> Sent: Friday, July 21, 2017 6:29<br>
> To: <a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
> Subject: [clang-tools-extra] r308738 - [clangd] Replace ASTUnit with manual<br>
> AST management.<br>
><br>
> Author: ibiryukov<br>
> Date: Fri Jul 21 06:29:29 2017<br>
> New Revision: 308738<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=308738&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=308738&view=rev</a><br>
> Log:<br>
> [clangd] Replace ASTUnit with manual AST management.<br>
><br>
> Summary:<br>
> This refactoring does not aim to introduce any significant changes to the<br>
> behaviour of clangd to keep the change as simple as possible.<br>
><br>
> Reviewers: klimek, krasimir, bkramer<br>
><br>
> Reviewed By: krasimir<br>
><br>
> Subscribers: malaperle, cfe-commits<br>
><br>
> Tags: #clang-tools-extra<br>
><br>
> Differential Revision: <a href="https://reviews.llvm.org/D35406" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D35406</a><br>
><br>
> Modified:<br>
>     clang-tools-extra/trunk/<wbr>clangd/ClangdServer.cpp<br>
>     clang-tools-extra/trunk/<wbr>clangd/ClangdUnit.cpp<br>
>     clang-tools-extra/trunk/<wbr>clangd/ClangdUnit.h<br>
><br>
> Modified: clang-tools-extra/trunk/<wbr>clangd/ClangdServer.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/clang-tools-</a><br>
> extra/trunk/clangd/<wbr>ClangdServer.cpp?rev=308738&<wbr>r1=308737&r2=308738&view=diff<br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- clang-tools-extra/trunk/<wbr>clangd/ClangdServer.cpp (original)<br>
> +++ clang-tools-extra/trunk/<wbr>clangd/ClangdServer.cpp Fri Jul 21 06:29:29<br>
</div></div>> +++ 2017<br>
<div><div class="h5">> @@ -205,14 +205,11 @@ ClangdServer::codeComplete(<wbr>PathRef File,<br>
><br>
>    std::vector<CompletionItem> Result;<br>
>    auto TaggedFS = FSProvider.<wbr>getTaggedFileSystem(File);<br>
> -  // It would be nice to use runOnUnitWithoutReparse here, but we can't<br>
> -  // guarantee the correctness of code completion cache here if we don't do<br>
> the<br>
> -  // reparse.<br>
> -  Units.runOnUnit(File, *OverridenContents, ResourceDir, CDB, PCHs,<br>
> -                  TaggedFS.Value, [&](ClangdUnit &Unit) {<br>
> -                    Result = Unit.codeComplete(*<wbr>OverridenContents, Pos,<br>
> -                                               TaggedFS.Value);<br>
> -                  });<br>
> +  Units.runOnUnitWithoutReparse(<wbr>File, *OverridenContents, ResourceDir, CDB,<br>
> +                                PCHs, TaggedFS.Value, [&](ClangdUnit &Unit) {<br>
> +                                  Result = Unit.codeComplete(<br>
> +                                      *OverridenContents, Pos,<br>
> TaggedFS.Value);<br>
> +                                });<br>
>    return make_tagged(std::move(Result), TaggedFS.Tag);  }<br>
><br>
><br>
> Modified: clang-tools-extra/trunk/<wbr>clangd/ClangdUnit.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/clang-tools-</a><br>
> extra/trunk/clangd/ClangdUnit.<wbr>cpp?rev=308738&r1=308737&r2=<wbr>308738&view=diff<br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- clang-tools-extra/trunk/<wbr>clangd/ClangdUnit.cpp (original)<br>
> +++ clang-tools-extra/trunk/<wbr>clangd/ClangdUnit.cpp Fri Jul 21 06:29:29<br>
</div></div>> +++ 2017<br>
<div><div class="h5">> @@ -9,16 +9,22 @@<br>
><br>
>  #include "ClangdUnit.h"<br>
><br>
> -#include "clang/Frontend/ASTUnit.h"<br>
>  #include "clang/Frontend/<wbr>CompilerInstance.h"<br>
>  #include "clang/Frontend/<wbr>CompilerInvocation.h"<br>
> +#include "clang/Frontend/<wbr>FrontendActions.h"<br>
>  #include "clang/Frontend/Utils.h"<br>
> -#include "clang/Index/IndexingAction.h"<br>
>  #include "clang/Index/<wbr>IndexDataConsumer.h"<br>
> +#include "clang/Index/IndexingAction.h"<br>
>  #include "clang/Lex/Lexer.h"<br>
>  #include "clang/Lex/MacroInfo.h"<br>
>  #include "clang/Lex/Preprocessor.h"<br>
> +#include "clang/Lex/<wbr>PreprocessorOptions.h"<br>
> +#include "clang/Sema/Sema.h"<br>
> +#include "clang/Serialization/<wbr>ASTWriter.h"<br>
>  #include "clang/Tooling/<wbr>CompilationDatabase.h"<br>
> +#include "llvm/ADT/ArrayRef.h"<br>
> +#include "llvm/ADT/SmallVector.h"<br>
> +#include "llvm/Support/<wbr>CrashRecoveryContext.h"<br>
>  #include "llvm/Support/Format.h"<br>
><br>
>  #include <algorithm><br>
> @@ -26,6 +32,196 @@<br>
>  using namespace clang::clangd;<br>
>  using namespace clang;<br>
><br>
> +namespace {<br>
> +<br>
> +class DeclTrackingASTConsumer : public ASTConsumer {<br>
> +public:<br>
> +  DeclTrackingASTConsumer(std::<wbr>vector<const Decl *> &TopLevelDecls)<br>
> +      : TopLevelDecls(TopLevelDecls) {}<br>
> +<br>
> +  bool HandleTopLevelDecl(<wbr>DeclGroupRef DG) override {<br>
> +    for (const Decl *D : DG) {<br>
> +      // ObjCMethodDecl are not actually top-level decls.<br>
> +      if (isa<ObjCMethodDecl>(D))<br>
> +        continue;<br>
> +<br>
> +      TopLevelDecls.push_back(D);<br>
> +    }<br>
> +    return true;<br>
> +  }<br>
> +<br>
> +private:<br>
> +  std::vector<const Decl *> &TopLevelDecls; };<br>
> +<br>
</div></div><span class="">> +class ClangdFrontendAction : public SyntaxOnlyAction {<br>
> +public:<br>
> +  std::vector<const Decl *> takeTopLevelDecls() {<br>
> +    return std::move(TopLevelDecls);<br>
> +  }<br>
> +<br>
> +protected:<br>
> +  std::unique_ptr<ASTConsumer> CreateASTConsumer(<wbr>CompilerInstance &CI,<br>
> +                                                 StringRef InFile) override {<br>
> +    return llvm::make_unique<<wbr>DeclTrackingASTConsumer>(/*<wbr>ref*/<br>
</span>> +TopLevelDecls);<br>
<span class="">> +  }<br>
> +<br>
> +private:<br>
> +  std::vector<const Decl *> TopLevelDecls; };<br>
> +<br>
</span><div><div class="h5">> +class ClangdUnitPreambleCallbacks : public PreambleCallbacks {<br>
> +public:<br>
> +  std::vector<serialization::<wbr>DeclID> takeTopLevelDeclIDs() {<br>
> +    return std::move(TopLevelDeclIDs);<br>
> +  }<br>
> +<br>
> +  void AfterPCHEmitted(ASTWriter &Writer) override {<br>
> +    TopLevelDeclIDs.reserve(<wbr>TopLevelDecls.size());<br>
> +    for (Decl *D : TopLevelDecls) {<br>
> +      // Invalid top-level decls may not have been serialized.<br>
> +      if (D->isInvalidDecl())<br>
> +        continue;<br>
> +      TopLevelDeclIDs.push_back(<wbr>Writer.getDeclID(D));<br>
> +    }<br>
> +  }<br>
> +<br>
> +  void HandleTopLevelDecl(<wbr>DeclGroupRef DG) override {<br>
> +    for (Decl *D : DG) {<br>
> +      if (isa<ObjCMethodDecl>(D))<br>
> +        continue;<br>
> +      TopLevelDecls.push_back(D);<br>
> +    }<br>
> +  }<br>
> +<br>
> +private:<br>
> +  std::vector<Decl *> TopLevelDecls;<br>
> +  std::vector<serialization::<wbr>DeclID> TopLevelDeclIDs; };<br>
> +<br>
</div></div><span class="">> +/// Convert from clang diagnostic level to LSP severity.<br>
> +static int getSeverity(DiagnosticsEngine:<wbr>:Level L) {<br>
> +  switch (L) {<br>
> +  case DiagnosticsEngine::Remark:<br>
> +    return 4;<br>
> +  case DiagnosticsEngine::Note:<br>
> +    return 3;<br>
> +  case DiagnosticsEngine::Warning:<br>
> +    return 2;<br>
> +  case DiagnosticsEngine::Fatal:<br>
> +  case DiagnosticsEngine::Error:<br>
> +    return 1;<br>
> +  case DiagnosticsEngine::Ignored:<br>
> +    return 0;<br>
> +  }<br>
> +  llvm_unreachable("Unknown diagnostic level!"); }<br>
> +<br>
</span><span class="">> +llvm::Optional<<wbr>DiagWithFixIts> toClangdDiag(StoredDiagnostic D) {<br>
> +  auto Location = D.getLocation();<br>
> +  if (!Location.isValid() || !Location.getManager().<wbr>isInMainFile(Location))<br>
> +    return llvm::None;<br>
> +<br>
> +  Position P;<br>
</span>> +  P.line = Location.<wbr>getSpellingLineNumber() - 1;  P.character =<br>
> + Location.<wbr>getSpellingColumnNumber();<br>
<span class="">> +  Range R = {P, P};<br>
> +  clangd::Diagnostic Diag = {R, getSeverity(D.getLevel()),<br>
</span>> + D.getMessage()};<br>
<span class="">> +<br>
> +  llvm::SmallVector<tooling::<wbr>Replacement, 1> FixItsForDiagnostic;<br>
> +  for (const FixItHint &Fix : D.getFixIts()) {<br>
> +    FixItsForDiagnostic.push_back(<wbr>clang::tooling::Replacement(<br>
> +        Location.getManager(), Fix.RemoveRange, Fix.CodeToInsert));<br>
> +  }<br>
> +  return DiagWithFixIts{Diag, std::move(FixItsForDiagnostic)<wbr>}; }<br>
> +<br>
</span><span class="">> +class StoreDiagsConsumer : public DiagnosticConsumer {<br>
> +public:<br>
> +  StoreDiagsConsumer(std::<wbr>vector<DiagWithFixIts> &Output) :<br>
</span>> +Output(Output) {}<br>
<span class="">> +<br>
> +  void HandleDiagnostic(<wbr>DiagnosticsEngine::Level DiagLevel,<br>
> +                        const clang::Diagnostic &Info) override {<br>
> +    DiagnosticConsumer::<wbr>HandleDiagnostic(DiagLevel, Info);<br>
> +<br>
> +    if (auto convertedDiag = toClangdDiag(StoredDiagnostic(<wbr>DiagLevel, Info)))<br>
> +      Output.push_back(std::move(*<wbr>convertedDiag));<br>
> +  }<br>
> +<br>
> +private:<br>
> +  std::vector<DiagWithFixIts> &Output;<br>
> +};<br>
> +<br>
> +class EmptyDiagsConsumer : public DiagnosticConsumer {<br>
> +public:<br>
> +  void HandleDiagnostic(<wbr>DiagnosticsEngine::Level DiagLevel,<br>
> +                        const clang::Diagnostic &Info) override {} };<br>
> +<br>
</span><span class="">> +std::unique_ptr<<wbr>CompilerInvocation><br>
> +createCompilerInvocation(<wbr>ArrayRef<const char *> ArgList,<br>
> +                         IntrusiveRefCntPtr<<wbr>DiagnosticsEngine> Diags,<br>
> +                         IntrusiveRefCntPtr<vfs::<wbr>FileSystem> VFS) {<br>
> +  auto CI = createInvocationFromCommandLin<wbr>e(ArgList, std::move(Diags),<br>
> +                                            std::move(VFS));<br>
> +  // We rely on CompilerInstance to manage the resource (i.e. free them<br>
</span>> +on<br>
<span class="">> +  // EndSourceFile), but that won't happen if DisableFree is set to true.<br>
> +  // Since createInvocationFromCommandLin<wbr>e sets it to true, we have to<br>
</span>> +override<br>
<span class="">> +  // it.<br>
> +  CI->getFrontendOpts().<wbr>DisableFree = false;<br>
> +  return CI;<br>
> +}<br>
> +<br>
> +/// Creates a CompilerInstance from \p CI, with main buffer overriden<br>
</span>> +to \p /// Buffer and arguments to read the PCH from \p Preamble, if \p<br>
> +Preamble is not /// null. Note that vfs::FileSystem inside returned<br>
> +instance may differ from \p /// VFS if additional file remapping were set in<br>
<span class="">> command-line arguments.<br>
> +/// On some errors, returns null. When non-null value is returned, it's<br>
</span>> +expected /// to be consumed by the FrontendAction as it will have a<br>
> +pointer to the \p /// Buffer that will only be deleted if BeginSourceFile is<br>
<span class="">> called.<br>
> +std::unique_ptr<<wbr>CompilerInstance><br>
> +prepareCompilerInstance(std::<wbr>unique_ptr<clang::<wbr>CompilerInvocation> CI,<br>
> +                        const PrecompiledPreamble *Preamble,<br>
> +                        std::unique_ptr<llvm::<wbr>MemoryBuffer> Buffer,<br>
> +                        std::shared_ptr<<wbr>PCHContainerOperations> PCHs,<br>
> +                        IntrusiveRefCntPtr<vfs::<wbr>FileSystem> VFS,<br>
> +                        DiagnosticConsumer &DiagsClient) {<br>
> +  assert(VFS && "VFS is null");<br>
> +  assert(!CI-><wbr>getPreprocessorOpts().<wbr>RetainRemappedFileBuffers &&<br>
> +         "Setting RetainRemappedFileBuffers to true will cause a memory leak<br>
> "<br>
> +         "of ContentsBuffer");<br>
> +<br>
> +  // NOTE: we use Buffer.get() when adding remapped files, so we have<br>
</span>> + to make  // sure it will be released if no error is emitted.<br>
> +  if (Preamble) {<br>
> +    Preamble->AddImplicitPreamble(<wbr>*CI, Buffer.get());  } else {<br>
<span class="">> +    CI->getPreprocessorOpts().<wbr>addRemappedFile(<br>
> +        CI->getFrontendOpts().Inputs[<wbr>0].getFile(), Buffer.get());  }<br>
> +<br>
> +  auto Clang = llvm::make_unique<<wbr>CompilerInstance>(PCHs);<br>
> +  Clang->setInvocation(std::<wbr>move(CI));<br>
> +  Clang->createDiagnostics(&<wbr>DiagsClient, false);<br>
> +<br>
> +  if (auto VFSWithRemapping = createVFSFromCompilerInvocatio<wbr>n(<br>
> +          Clang->getInvocation(), Clang->getDiagnostics(), VFS))<br>
> +    VFS = VFSWithRemapping;<br>
> +  Clang->setVirtualFileSystem(<wbr>VFS);<br>
> +<br>
> +  Clang->setTarget(TargetInfo::<wbr>CreateTargetInfo(<br>
> +      Clang->getDiagnostics(), Clang->getInvocation().<wbr>TargetOpts));<br>
> +  if (!Clang->hasTarget())<br>
> +    return nullptr;<br>
> +<br>
> +  // RemappedFileBuffers will handle the lifetime of the Buffer<br>
</span>> +pointer,<br>
<div><div class="h5">> +  // release it.<br>
> +  Buffer.release();<br>
> +  return Clang;<br>
> +}<br>
> +<br>
> +} // namespace<br>
> +<br>
>  ClangdUnit::ClangdUnit(PathRef FileName, StringRef Contents,<br>
>                         StringRef ResourceDir,<br>
>                         std::shared_ptr<<wbr>PCHContainerOperations> PCHs, @@ -<br>
> 39,44 +235,54 @@ ClangdUnit::ClangdUnit(PathRef FileName,<br>
>    Commands.front().CommandLine.<wbr>push_back("-resource-dir=" +<br>
>                                           std::string(ResourceDir));<br>
><br>
> -  IntrusiveRefCntPtr<<wbr>DiagnosticsEngine> Diags =<br>
> -      CompilerInstance::<wbr>createDiagnostics(new DiagnosticOptions);<br>
> -<br>
> -  std::vector<const char *> ArgStrs;<br>
> -  for (const auto &S : Commands.front().CommandLine)<br>
> -    ArgStrs.push_back(S.c_str());<br>
> -<br>
> -  ASTUnit::RemappedFile RemappedSource(<br>
> -      FileName,<br>
> -      llvm::MemoryBuffer::<wbr>getMemBufferCopy(Contents, FileName).release());<br>
> -<br>
> -  auto ArgP = &*ArgStrs.begin();<br>
> -  Unit = std::unique_ptr<ASTUnit>(<wbr>ASTUnit::LoadFromCommandLine(<br>
> -      ArgP, ArgP + ArgStrs.size(), PCHs, Diags, ResourceDir,<br>
> -      /*OnlyLocalDecls=*/false, /*CaptureDiagnostics=*/true, RemappedSource,<br>
> -      /*<wbr>RemappedFilesKeepOriginalName=<wbr>*/true,<br>
> -      /*<wbr>PrecompilePreambleAfterNParses<wbr>=*/1, /*TUKind=*/TU_Prefix,<br>
> -      /*CacheCodeCompletionResults=*<wbr>/true,<br>
> -      /*<wbr>IncludeBriefCommentsInCodeComp<wbr>letion=*/true,<br>
> -      /*AllowPCHWithCompilerErrors=*<wbr>/true,<br>
> -      /*SkipFunctionBodies=*/false,<br>
> -      /*SingleFileParse=*/false,<br>
> -      /*UserFilesAreVolatile=*/<wbr>false, /*ForSerialization=*/false,<br>
> -      /*ModuleFormat=*/llvm::None,<br>
> -      /*ErrAST=*/nullptr, VFS));<br>
> -  assert(Unit && "Unit wasn't created");<br>
</div></div>> +  Command = std::move(Commands.front());  reparse(Contents, VFS);<br>
<div class="HOEnZb"><div class="h5">>  }<br>
><br>
>  void ClangdUnit::reparse(StringRef Contents,<br>
>                           IntrusiveRefCntPtr<vfs::<wbr>FileSystem> VFS) {<br>
> -  // Do a reparse if this wasn't the first parse.<br>
> -  // FIXME: This might have the wrong working directory if it changed in the<br>
> -  // meantime.<br>
> -  ASTUnit::RemappedFile RemappedSource(<br>
> -      FileName,<br>
> -      llvm::MemoryBuffer::<wbr>getMemBufferCopy(Contents, FileName).release());<br>
> +  std::vector<const char *> ArgStrs;<br>
> +  for (const auto &S : Command.CommandLine)<br>
> +    ArgStrs.push_back(S.c_str());<br>
><br>
> -  Unit->Reparse(PCHs, RemappedSource, VFS);<br>
> +  std::unique_ptr<<wbr>CompilerInvocation> CI;<br>
> +  {<br>
> +    // FIXME(ibiryukov): store diagnostics from CommandLine when we start<br>
> +    // reporting them.<br>
> +    EmptyDiagsConsumer CommandLineDiagsConsumer;<br>
> +    IntrusiveRefCntPtr<<wbr>DiagnosticsEngine> CommandLineDiagsEngine =<br>
> +        CompilerInstance::<wbr>createDiagnostics(new DiagnosticOptions,<br>
> +                                            &CommandLineDiagsConsumer,<br>
> false);<br>
> +    CI = createCompilerInvocation(<wbr>ArgStrs, CommandLineDiagsEngine, VFS);<br>
> +  }<br>
> +  assert(CI && "Couldn't create CompilerInvocation");<br>
> +<br>
> +  std::unique_ptr<llvm::<wbr>MemoryBuffer> ContentsBuffer =<br>
> +      llvm::MemoryBuffer::<wbr>getMemBufferCopy(Contents, FileName);<br>
> +<br>
> +  // Rebuild the preamble if it is missing or can not be reused.<br>
> +  auto Bounds =<br>
> +      ComputePreambleBounds(*CI-><wbr>getLangOpts(), ContentsBuffer.get(), 0);<br>
> +  if (!Preamble || !Preamble->Preamble.CanReuse(*<wbr>CI, ContentsBuffer.get(),<br>
> +                                                Bounds, VFS.get())) {<br>
> +    std::vector<DiagWithFixIts> PreambleDiags;<br>
> +    StoreDiagsConsumer PreambleDiagnosticsConsumer(/*<wbr>ref*/ PreambleDiags);<br>
> +    IntrusiveRefCntPtr<<wbr>DiagnosticsEngine> PreambleDiagsEngine =<br>
> +        CompilerInstance::<wbr>createDiagnostics(<br>
> +            &CI->getDiagnosticOpts(), &PreambleDiagnosticsConsumer, false);<br>
> +    ClangdUnitPreambleCallbacks SerializedDeclsCollector;<br>
> +    auto BuiltPreamble = PrecompiledPreamble::Build(<br>
> +        *CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine, VFS, PCHs,<br>
> +        SerializedDeclsCollector);<br>
> +    if (BuiltPreamble)<br>
> +      Preamble = PreambleData(std::move(*<wbr>BuiltPreamble),<br>
> +                              SerializedDeclsCollector.<wbr>takeTopLevelDeclIDs(),<br>
> +                              std::move(PreambleDiags));<br>
> +  }<br>
> +  Unit = ParsedAST::Build(<br>
> +      std::move(CI), Preamble ? &Preamble->Preamble : nullptr,<br>
> +      Preamble ? llvm::makeArrayRef(Preamble-><wbr>TopLevelDeclIDs) : llvm::None,<br>
> +      std::move(ContentsBuffer), PCHs, VFS);<br>
>  }<br>
><br>
>  namespace {<br>
> @@ -188,97 +394,164 @@ public:<br>
>  std::vector<CompletionItem><br>
>  ClangdUnit::codeComplete(<wbr>StringRef Contents, Position Pos,<br>
>                           IntrusiveRefCntPtr<vfs::<wbr>FileSystem> VFS) {<br>
> -  CodeCompleteOptions CCO;<br>
> -  CCO.IncludeBriefComments = 1;<br>
> -  // This is where code completion stores dirty buffers. Need to free after<br>
> -  // completion.<br>
> -  SmallVector<const llvm::MemoryBuffer *, 4> OwnedBuffers;<br>
> -  SmallVector<StoredDiagnostic, 4> StoredDiagnostics;<br>
> -  IntrusiveRefCntPtr<<wbr>DiagnosticsEngine> DiagEngine(<br>
> -      new DiagnosticsEngine(new DiagnosticIDs, new DiagnosticOptions));<br>
> -  std::vector<CompletionItem> Items;<br>
> -  CompletionItemsCollector Collector(&Items, CCO);<br>
> +  std::vector<const char *> ArgStrs;<br>
> +  for (const auto &S : Command.CommandLine)<br>
> +    ArgStrs.push_back(S.c_str());<br>
><br>
> -  ASTUnit::RemappedFile RemappedSource(<br>
> -      FileName,<br>
> -      llvm::MemoryBuffer::<wbr>getMemBufferCopy(Contents, FileName).release());<br>
> -<br>
> -  IntrusiveRefCntPtr<<wbr>FileManager> FileMgr(<br>
> -      new FileManager(Unit-><wbr>getFileSystemOpts(), VFS));<br>
> -  IntrusiveRefCntPtr<<wbr>SourceManager> SourceMgr(<br>
> -      new SourceManager(*DiagEngine, *FileMgr));<br>
> -  // CodeComplete seems to require fresh LangOptions.<br>
> -  LangOptions LangOpts = Unit->getLangOpts();<br>
> -  // The language server protocol uses zero-based line and column numbers.<br>
> -  // The clang code completion uses one-based numbers.<br>
> -  Unit->CodeComplete(FileName, Pos.line + 1, Pos.character + 1,<br>
> RemappedSource,<br>
> -                     CCO.IncludeMacros, CCO.IncludeCodePatterns,<br>
> -                     CCO.IncludeBriefComments, Collector, PCHs, *DiagEngine,<br>
> -                     LangOpts, *SourceMgr, *FileMgr, StoredDiagnostics,<br>
> -                     OwnedBuffers);<br>
> -  for (const llvm::MemoryBuffer *Buffer : OwnedBuffers)<br>
> -    delete Buffer;<br>
> -  return Items;<br>
> -}<br>
> +  std::unique_ptr<<wbr>CompilerInvocation> CI;<br>
> +  EmptyDiagsConsumer DummyDiagsConsumer;<br>
> +  {<br>
> +    IntrusiveRefCntPtr<<wbr>DiagnosticsEngine> CommandLineDiagsEngine =<br>
> +        CompilerInstance::<wbr>createDiagnostics(new DiagnosticOptions,<br>
> +                                            &DummyDiagsConsumer, false);<br>
> +    CI = createCompilerInvocation(<wbr>ArgStrs, CommandLineDiagsEngine, VFS);<br>
> +  }<br>
> +  assert(CI && "Couldn't create CompilerInvocation");<br>
> +<br>
> +  std::unique_ptr<llvm::<wbr>MemoryBuffer> ContentsBuffer =<br>
> +      llvm::MemoryBuffer::<wbr>getMemBufferCopy(Contents, FileName);<br>
> +<br>
> +  // Attempt to reuse the PCH from precompiled preamble, if it was built.<br>
> +  const PrecompiledPreamble *PreambleForCompletion = nullptr;<br>
> +  if (Preamble) {<br>
> +    auto Bounds =<br>
> +        ComputePreambleBounds(*CI-><wbr>getLangOpts(), ContentsBuffer.get(), 0);<br>
> +    if (Preamble->Preamble.CanReuse(*<wbr>CI, ContentsBuffer.get(), Bounds,<br>
> +                                    VFS.get()))<br>
> +      PreambleForCompletion = &Preamble->Preamble;<br>
> +  }<br>
> +<br>
> +  auto Clang = prepareCompilerInstance(std::<wbr>move(CI), PreambleForCompletion,<br>
> +                                       std::move(ContentsBuffer), PCHs, VFS,<br>
> +                                       DummyDiagsConsumer);<br>
> +  auto &DiagOpts = Clang->getDiagnosticOpts();<br>
> +  DiagOpts.IgnoreWarnings = true;<br>
> +<br>
> +  auto &FrontendOpts = Clang->getFrontendOpts();<br>
> +  FrontendOpts.<wbr>SkipFunctionBodies = true;<br>
> +<br>
> +  FrontendOpts.CodeCompleteOpts.<wbr>IncludeGlobals = true;<br>
> +  // we don't handle code patterns properly yet, disable them.<br>
> +  FrontendOpts.CodeCompleteOpts.<wbr>IncludeCodePatterns = false;<br>
> +  FrontendOpts.CodeCompleteOpts.<wbr>IncludeMacros = true;<br>
> +  FrontendOpts.CodeCompleteOpts.<wbr>IncludeBriefComments = true;<br>
> +<br>
> +  FrontendOpts.CodeCompletionAt.<wbr>FileName = FileName;<br>
> +  FrontendOpts.CodeCompletionAt.<wbr>Line = Pos.line + 1;<br>
> +  FrontendOpts.CodeCompletionAt.<wbr>Column = Pos.character + 1;<br>
><br>
> -namespace {<br>
> -/// Convert from clang diagnostic level to LSP severity.<br>
> -static int getSeverity(DiagnosticsEngine:<wbr>:Level L) {<br>
> -  switch (L) {<br>
> -  case DiagnosticsEngine::Remark:<br>
> -    return 4;<br>
> -  case DiagnosticsEngine::Note:<br>
> -    return 3;<br>
> -  case DiagnosticsEngine::Warning:<br>
> -    return 2;<br>
> -  case DiagnosticsEngine::Fatal:<br>
> -  case DiagnosticsEngine::Error:<br>
> -    return 1;<br>
> -  case DiagnosticsEngine::Ignored:<br>
> -    return 0;<br>
> +  std::vector<CompletionItem> Items;<br>
> +  Clang-><wbr>setCodeCompletionConsumer(<br>
> +      new CompletionItemsCollector(&<wbr>Items, FrontendOpts.CodeCompleteOpts)<wbr>);<br>
> +<br>
> +  SyntaxOnlyAction Action;<br>
> +  if (!Action.BeginSourceFile(*<wbr>Clang, Clang->getFrontendOpts().<wbr>Inputs[0])) {<br>
> +    // FIXME(ibiryukov): log errors<br>
> +    return Items;<br>
>    }<br>
> -  llvm_unreachable("Unknown diagnostic level!");<br>
> +  if (!Action.Execute()) {<br>
> +    // FIXME(ibiryukov): log errors<br>
> +  }<br>
> +  Action.EndSourceFile();<br>
> +<br>
> +  return Items;<br>
>  }<br>
> -} // namespace<br>
><br>
>  std::vector<DiagWithFixIts> ClangdUnit::<wbr>getLocalDiagnostics() const {<br>
> +  if (!Unit)<br>
> +    return {}; // Parsing failed.<br>
> +<br>
>    std::vector<DiagWithFixIts> Result;<br>
> -  for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),<br>
> -                                     DEnd = Unit->stored_diag_end();<br>
> -       D != DEnd; ++D) {<br>
> -    if (!D->getLocation().isValid() ||<br>
> -        !D->getLocation().getManager()<wbr>.isInMainFile(D->getLocation()<wbr>))<br>
> -      continue;<br>
> -    Position P;<br>
> -    P.line = D->getLocation().<wbr>getSpellingLineNumber() - 1;<br>
> -    P.character = D->getLocation().<wbr>getSpellingColumnNumber();<br>
> -    Range R = {P, P};<br>
> -    clangd::Diagnostic Diag = {R, getSeverity(D->getLevel()), D-<br>
> >getMessage()};<br>
> -<br>
> -    llvm::SmallVector<tooling::<wbr>Replacement, 1> FixItsForDiagnostic;<br>
> -    for (const FixItHint &Fix : D->getFixIts()) {<br>
> -      FixItsForDiagnostic.push_back(<wbr>clang::tooling::Replacement(<br>
> -          Unit->getSourceManager(), Fix.RemoveRange, Fix.CodeToInsert));<br>
> -    }<br>
> -    Result.push_back({Diag, std::move(FixItsForDiagnostic)<wbr>});<br>
> -  }<br>
> +  auto PreambleDiagsSize = Preamble ? Preamble->Diags.size() : 0;<br>
> +  const auto &Diags = Unit->getDiagnostics();<br>
> +  Result.reserve(<wbr>PreambleDiagsSize + Diags.size());<br>
> +<br>
> +  if (Preamble)<br>
> +    Result.insert(Result.end(), Preamble->Diags.begin(), Preamble-<br>
> >Diags.end());<br>
> +  Result.insert(Result.end(), Diags.begin(), Diags.end());<br>
>    return Result;<br>
>  }<br>
><br>
>  void ClangdUnit::dumpAST(llvm::raw_<wbr>ostream &OS) const {<br>
> +  if (!Unit) {<br>
> +    OS << "<no-ast-in-clang>";<br>
> +    return; // Parsing failed.<br>
> +  }<br>
>    Unit->getASTContext().<wbr>getTranslationUnitDecl()-><wbr>dump(OS, true);<br>
>  }<br>
><br>
> +llvm::Optional<ClangdUnit::<wbr>ParsedAST><br>
> +ClangdUnit::ParsedAST::Build(<wbr>std::unique_ptr<clang::<wbr>CompilerInvocation> CI,<br>
> +                             const PrecompiledPreamble *Preamble,<br>
> +                             ArrayRef<serialization::<wbr>DeclID> PreambleDeclIDs,<br>
> +                             std::unique_ptr<llvm::<wbr>MemoryBuffer> Buffer,<br>
> +                             std::shared_ptr<<wbr>PCHContainerOperations> PCHs,<br>
> +                             IntrusiveRefCntPtr<vfs::<wbr>FileSystem> VFS) {<br>
> +<br>
> +  std::vector<DiagWithFixIts> ASTDiags;<br>
> +  StoreDiagsConsumer UnitDiagsConsumer(/*ref*/ ASTDiags);<br>
> +<br>
> +  auto Clang =<br>
> +      prepareCompilerInstance(std::<wbr>move(CI), Preamble, std::move(Buffer),<br>
> PCHs,<br>
> +                              VFS, /*ref*/ UnitDiagsConsumer);<br>
> +<br>
> +  // Recover resources if we crash before exiting this method.<br>
> +  llvm::<wbr>CrashRecoveryContextCleanupReg<wbr>istrar<CompilerInstance> CICleanup(<br>
> +      Clang.get());<br>
> +<br>
> +  auto Action = llvm::make_unique<<wbr>ClangdFrontendAction>();<br>
> +  if (!Action->BeginSourceFile(*<wbr>Clang, Clang->getFrontendOpts().<wbr>Inputs[0])) {<br>
> +    // FIXME(ibiryukov): log error<br>
> +    return llvm::None;<br>
> +  }<br>
> +  if (!Action->Execute()) {<br>
> +    // FIXME(ibiryukov): log error<br>
> +  }<br>
> +<br>
> +  // UnitDiagsConsumer is local, we can not store it in CompilerInstance that<br>
> +  // has a longer lifetime.<br>
> +  Clang->getDiagnostics().<wbr>setClient(new EmptyDiagsConsumer);<br>
> +<br>
> +  std::vector<const Decl *> ParsedDecls = Action->takeTopLevelDecls();<br>
> +  std::vector<serialization::<wbr>DeclID> PendingDecls;<br>
> +  if (Preamble) {<br>
> +    PendingDecls.reserve(<wbr>PreambleDeclIDs.size());<br>
> +    PendingDecls.insert(<wbr>PendingDecls.begin(), PreambleDeclIDs.begin(),<br>
> +                        PreambleDeclIDs.end());<br>
> +  }<br>
> +<br>
> +  return ParsedAST(std::move(Clang), std::move(Action),<br>
> std::move(ParsedDecls),<br>
> +                   std::move(PendingDecls), std::move(ASTDiags));<br>
> +}<br>
> +<br>
>  namespace {<br>
> +<br>
> +SourceLocation getMacroArgExpandedLocation(<wbr>const SourceManager &Mgr,<br>
> +                                           const FileEntry *FE,<br>
> +                                           unsigned Offset) {<br>
> +  SourceLocation FileLoc = Mgr.translateFileLineCol(FE, 1, 1);<br>
> +  return Mgr.<wbr>getMacroArgExpandedLocation(<wbr>FileLoc.getLocWithOffset(<wbr>Offset));<br>
> +}<br>
> +<br>
> +SourceLocation getMacroArgExpandedLocation(<wbr>const SourceManager &Mgr,<br>
> +                                           const FileEntry *FE, Position Pos)<br>
> {<br>
> +  SourceLocation InputLoc =<br>
> +      Mgr.translateFileLineCol(FE, Pos.line + 1, Pos.character + 1);<br>
> +  return Mgr.<wbr>getMacroArgExpandedLocation(<wbr>InputLoc);<br>
> +}<br>
> +<br>
>  /// Finds declarations locations that a given source location refers to.<br>
>  class DeclarationLocationsFinder : public index::IndexDataConsumer {<br>
>    std::vector<Location> DeclarationLocations;<br>
>    const SourceLocation &SearchedLocation;<br>
> -  ASTUnit &Unit;<br>
> +  const ASTContext &AST;<br>
> +  Preprocessor &PP;<br>
> +<br>
>  public:<br>
>    DeclarationLocationsFinder(<wbr>raw_ostream &OS,<br>
> -      const SourceLocation &SearchedLocation, ASTUnit &Unit) :<br>
> -      SearchedLocation(<wbr>SearchedLocation), Unit(Unit) {}<br>
> +                             const SourceLocation &SearchedLocation,<br>
> +                             ASTContext &AST, Preprocessor &PP)<br>
> +      : SearchedLocation(<wbr>SearchedLocation), AST(AST), PP(PP) {}<br>
><br>
>    std::vector<Location> takeLocations() {<br>
>      // Don't keep the same location multiple times.<br>
> @@ -302,17 +575,17 @@ public:<br>
><br>
>  private:<br>
>    bool isSearchedLocation(FileID FID, unsigned Offset) const {<br>
> -    const SourceManager &SourceMgr = Unit.getSourceManager();<br>
> -    return SourceMgr.getFileOffset(<wbr>SearchedLocation) == Offset<br>
> -        && SourceMgr.getFileID(<wbr>SearchedLocation) == FID;<br>
> +    const SourceManager &SourceMgr = AST.getSourceManager();<br>
> +    return SourceMgr.getFileOffset(<wbr>SearchedLocation) == Offset &&<br>
> +           SourceMgr.getFileID(<wbr>SearchedLocation) == FID;<br>
>    }<br>
><br>
> -  void addDeclarationLocation(const SourceRange& ValSourceRange) {<br>
> -    const SourceManager& SourceMgr = Unit.getSourceManager();<br>
> -    const LangOptions& LangOpts = Unit.getLangOpts();<br>
> +  void addDeclarationLocation(const SourceRange &ValSourceRange) {<br>
> +    const SourceManager &SourceMgr = AST.getSourceManager();<br>
> +    const LangOptions &LangOpts = AST.getLangOpts();<br>
>      SourceLocation LocStart = ValSourceRange.getBegin();<br>
>      SourceLocation LocEnd =<br>
> Lexer::getLocForEndOfToken(<wbr>ValSourceRange.getEnd(),<br>
> -        0, SourceMgr, LangOpts);<br>
> +                                                       0, SourceMgr,<br>
> LangOpts);<br>
>      Position Begin;<br>
>      Begin.line = SourceMgr.<wbr>getSpellingLineNumber(<wbr>LocStart) - 1;<br>
>      Begin.character = SourceMgr.<wbr>getSpellingColumnNumber(<wbr>LocStart) - 1;<br>
> @@ -330,24 +603,24 @@ private:<br>
>    void finish() override {<br>
>      // Also handle possible macro at the searched location.<br>
>      Token Result;<br>
> -    if (!Lexer::getRawToken(<wbr>SearchedLocation, Result,<br>
> Unit.getSourceManager(),<br>
> -        Unit.getASTContext().<wbr>getLangOpts(), false)) {<br>
> +    if (!Lexer::getRawToken(<wbr>SearchedLocation, Result, AST.getSourceManager(),<br>
> +                            AST.getLangOpts(), false)) {<br>
>        if (Result.is(tok::raw_<wbr>identifier)) {<br>
> -        Unit.getPreprocessor().<wbr>LookUpIdentifierInfo(Result);<br>
> +        PP.LookUpIdentifierInfo(<wbr>Result);<br>
>        }<br>
> -      IdentifierInfo* IdentifierInfo = Result.getIdentifierInfo();<br>
> +      IdentifierInfo *IdentifierInfo = Result.getIdentifierInfo();<br>
>        if (IdentifierInfo && IdentifierInfo-><wbr>hadMacroDefinition()) {<br>
>          std::pair<FileID, unsigned int> DecLoc =<br>
> -<br>
> Unit.getSourceManager().<wbr>getDecomposedExpansionLoc(<wbr>SearchedLocation);<br>
> +<br>
> AST.getSourceManager().<wbr>getDecomposedExpansionLoc(<wbr>SearchedLocation);<br>
>          // Get the definition just before the searched location so that a<br>
> macro<br>
>          // referenced in a '#undef MACRO' can still be found.<br>
> -        SourceLocation BeforeSearchedLocation = Unit.getLocation(<br>
> -            Unit.getSourceManager().<wbr>getFileEntryForID(DecLoc.<wbr>first),<br>
> +        SourceLocation BeforeSearchedLocation = getMacroArgExpandedLocation(<br>
> +            AST.getSourceManager(),<br>
> +            AST.getSourceManager().<wbr>getFileEntryForID(DecLoc.<wbr>first),<br>
>              DecLoc.second - 1);<br>
>          MacroDefinition MacroDef =<br>
> -            Unit.getPreprocessor().<wbr>getMacroDefinitionAtLoc(<wbr>IdentifierInfo,<br>
> -                BeforeSearchedLocation);<br>
> -        MacroInfo* MacroInf = MacroDef.getMacroInfo();<br>
> +            PP.getMacroDefinitionAtLoc(<wbr>IdentifierInfo,<br>
> BeforeSearchedLocation);<br>
> +        MacroInfo *MacroInf = MacroDef.getMacroInfo();<br>
>          if (MacroInf) {<br>
>            addDeclarationLocation(<br>
>                SourceRange(MacroInf-><wbr>getDefinitionLoc(),<br>
> @@ -360,30 +633,41 @@ private:<br>
>  } // namespace<br>
><br>
>  std::vector<Location> ClangdUnit::findDefinitions(<wbr>Position Pos) {<br>
> -  const FileEntry *FE = Unit->getFileManager().<wbr>getFile(Unit-<br>
> >getMainFileName());<br>
> +  if (!Unit)<br>
> +    return {}; // Parsing failed.<br>
> +<br>
> +  const SourceManager &SourceMgr = Unit->getASTContext().<wbr>getSourceManager();<br>
> +  const FileEntry *FE =<br>
> SourceMgr.getFileEntryForID(<wbr>SourceMgr.getMainFileID());<br>
>    if (!FE)<br>
>      return {};<br>
><br>
>    SourceLocation SourceLocationBeg = getBeginningOfIdentifier(Pos, FE);<br>
><br>
>    auto DeclLocationsFinder = std::make_shared<<wbr>DeclarationLocationsFinder>(<br>
> -      llvm::errs(), SourceLocationBeg, *Unit);<br>
> +      llvm::errs(), SourceLocationBeg, Unit->getASTContext(),<br>
> +      Unit->getPreprocessor());<br>
>    index::IndexingOptions IndexOpts;<br>
>    IndexOpts.SystemSymbolFilter =<br>
>        index::IndexingOptions::<wbr>SystemSymbolFilterKind::All;<br>
>    IndexOpts.IndexFunctionLocals = true;<br>
> -  index::indexASTUnit(*Unit, DeclLocationsFinder, IndexOpts);<br>
> +<br>
> +  indexTopLevelDecls(Unit-><wbr>getASTContext(), Unit->getTopLevelDecls(),<br>
> +                     DeclLocationsFinder, IndexOpts);<br>
><br>
>    return DeclLocationsFinder-><wbr>takeLocations();<br>
>  }<br>
><br>
>  SourceLocation ClangdUnit::<wbr>getBeginningOfIdentifier(const Position &Pos,<br>
> -    const FileEntry *FE) const {<br>
> +                                                    const FileEntry *FE)<br>
> const {<br>
> +<br>
>    // The language server protocol uses zero-based line and column numbers.<br>
>    // Clang uses one-based numbers.<br>
> -  SourceLocation InputLocation = Unit->getLocation(FE, Pos.line + 1,<br>
> -      Pos.character + 1);<br>
><br>
> +  const ASTContext &AST = Unit->getASTContext();<br>
> +  const SourceManager &SourceMgr = AST.getSourceManager();<br>
> +<br>
> +  SourceLocation InputLocation =<br>
> +      getMacroArgExpandedLocation(<wbr>SourceMgr, FE, Pos);<br>
>    if (Pos.character == 0) {<br>
>      return InputLocation;<br>
>    }<br>
> @@ -396,20 +680,97 @@ SourceLocation ClangdUnit::getBeginningO<br>
>    // token. If so, Take the beginning of this token.<br>
>    // (It should be the same identifier because you can't have two adjacent<br>
>    // identifiers without another token in between.)<br>
> -  SourceLocation PeekBeforeLocation = Unit->getLocation(FE, Pos.line + 1,<br>
> -      Pos.character);<br>
> -  const SourceManager &SourceMgr = Unit->getSourceManager();<br>
> +  SourceLocation PeekBeforeLocation = getMacroArgExpandedLocation(<br>
> +      SourceMgr, FE, Position{Pos.line, Pos.character - 1});<br>
>    Token Result;<br>
>    if (Lexer::getRawToken(<wbr>PeekBeforeLocation, Result, SourceMgr,<br>
> -                         Unit->getASTContext().<wbr>getLangOpts(), false)) {<br>
> +                         AST.getLangOpts(), false)) {<br>
>      // getRawToken failed, just use InputLocation.<br>
>      return InputLocation;<br>
>    }<br>
><br>
>    if (Result.is(tok::raw_<wbr>identifier)) {<br>
>      return Lexer::GetBeginningOfToken(<wbr>PeekBeforeLocation, SourceMgr,<br>
> -        Unit->getASTContext().<wbr>getLangOpts());<br>
> +                                      Unit->getASTContext().<wbr>getLangOpts());<br>
>    }<br>
><br>
>    return InputLocation;<br>
>  }<br>
> +<br>
> +void ClangdUnit::ParsedAST::<wbr>ensurePreambleDeclsDeserialize<wbr>d() {<br>
> +  if (PendingTopLevelDecls.empty())<br>
> +    return;<br>
> +<br>
> +  std::vector<const Decl *> Resolved;<br>
> +  Resolved.reserve(<wbr>PendingTopLevelDecls.size());<br>
> +<br>
> +  ExternalASTSource &Source = *getASTContext().<wbr>getExternalSource();<br>
> +  for (serialization::DeclID TopLevelDecl : PendingTopLevelDecls) {<br>
> +    // Resolve the declaration ID to an actual declaration, possibly<br>
> +    // deserializing the declaration in the process.<br>
> +    if (Decl *D = Source.GetExternalDecl(<wbr>TopLevelDecl))<br>
> +      Resolved.push_back(D);<br>
> +  }<br>
> +<br>
> +  TopLevelDecls.reserve(<wbr>TopLevelDecls.size() + PendingTopLevelDecls.size());<br>
> +  TopLevelDecls.insert(<wbr>TopLevelDecls.begin(), Resolved.begin(),<br>
> Resolved.end());<br>
> +<br>
> +  PendingTopLevelDecls.clear();<br>
> +}<br>
> +<br>
> +ClangdUnit::ParsedAST::<wbr>ParsedAST(ParsedAST &&Other) = default;<br>
> +<br>
> +ClangdUnit::ParsedAST &ClangdUnit::ParsedAST::<br>
> +operator=(ParsedAST &&Other) = default;<br>
> +<br>
> +ClangdUnit::ParsedAST::~<wbr>ParsedAST() {<br>
> +  if (Action) {<br>
> +    Action->EndSourceFile();<br>
> +  }<br>
> +}<br>
> +<br>
> +ASTContext &ClangdUnit::ParsedAST::<wbr>getASTContext() {<br>
> +  return Clang->getASTContext();<br>
> +}<br>
> +<br>
> +const ASTContext &ClangdUnit::ParsedAST::<wbr>getASTContext() const {<br>
> +  return Clang->getASTContext();<br>
> +}<br>
> +<br>
> +Preprocessor &ClangdUnit::ParsedAST::<wbr>getPreprocessor() {<br>
> +  return Clang->getPreprocessor();<br>
> +}<br>
> +<br>
> +const Preprocessor &ClangdUnit::ParsedAST::<wbr>getPreprocessor() const {<br>
> +  return Clang->getPreprocessor();<br>
> +}<br>
> +<br>
> +ArrayRef<const Decl *> ClangdUnit::ParsedAST::<wbr>getTopLevelDecls() {<br>
> +  ensurePreambleDeclsDeserialize<wbr>d();<br>
> +  return TopLevelDecls;<br>
> +}<br>
> +<br>
> +const std::vector<DiagWithFixIts> &<br>
> +ClangdUnit::ParsedAST::<wbr>getDiagnostics() const {<br>
> +  return Diags;<br>
> +}<br>
> +<br>
> +ClangdUnit::ParsedAST::<wbr>ParsedAST(<br>
> +    std::unique_ptr<<wbr>CompilerInstance> Clang,<br>
> +    std::unique_ptr<<wbr>FrontendAction> Action,<br>
> +    std::vector<const Decl *> TopLevelDecls,<br>
> +    std::vector<serialization::<wbr>DeclID> PendingTopLevelDecls,<br>
> +    std::vector<DiagWithFixIts> Diags)<br>
> +    : Clang(std::move(Clang)), Action(std::move(Action)),<br>
> +      Diags(std::move(Diags)), TopLevelDecls(std::move(<wbr>TopLevelDecls)),<br>
> +      PendingTopLevelDecls(std::<wbr>move(PendingTopLevelDecls)) {<br>
> +  assert(this->Clang);<br>
> +  assert(this->Action);<br>
> +}<br>
> +<br>
> +ClangdUnit::PreambleData::<wbr>PreambleData(<br>
> +    PrecompiledPreamble Preamble,<br>
> +    std::vector<serialization::<wbr>DeclID> TopLevelDeclIDs,<br>
> +    std::vector<DiagWithFixIts> Diags)<br>
> +    : Preamble(std::move(Preamble)),<br>
> +      TopLevelDeclIDs(std::move(<wbr>TopLevelDeclIDs)), Diags(std::move(Diags)) {}<br>
><br>
> Modified: clang-tools-extra/trunk/<wbr>clangd/ClangdUnit.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/clang-tools-</a><br>
> extra/trunk/clangd/ClangdUnit.<wbr>h?rev=308738&r1=308737&r2=<wbr>308738&view=diff<br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- clang-tools-extra/trunk/<wbr>clangd/ClangdUnit.h (original)<br>
> +++ clang-tools-extra/trunk/<wbr>clangd/ClangdUnit.h Fri Jul 21 06:29:29 2017<br>
> @@ -13,6 +13,9 @@<br>
>  #include "Path.h"<br>
>  #include "Protocol.h"<br>
>  #include "clang/Frontend/ASTUnit.h"<br>
> +#include "clang/Frontend/<wbr>PrecompiledPreamble.h"<br>
> +#include "clang/Serialization/<wbr>ASTBitCodes.h"<br>
> +#include "clang/Tooling/<wbr>CompilationDatabase.h"<br>
>  #include "clang/Tooling/Core/<wbr>Replacement.h"<br>
>  #include <memory><br>
><br>
> @@ -70,11 +73,82 @@ public:<br>
>    void dumpAST(llvm::raw_ostream &OS) const;<br>
><br>
>  private:<br>
> +  /// Stores and provides access to parsed AST.<br>
> +  class ParsedAST {<br>
> +  public:<br>
> +    /// Attempts to run Clang and store parsed AST. If \p Preamble is non-<br>
> null<br>
> +    /// it is reused during parsing.<br>
> +    static llvm::Optional<ParsedAST><br>
> +    Build(std::unique_ptr<clang::<wbr>CompilerInvocation> CI,<br>
> +          const PrecompiledPreamble *Preamble,<br>
> +          ArrayRef<serialization::<wbr>DeclID> PreambleDeclIDs,<br>
> +          std::unique_ptr<llvm::<wbr>MemoryBuffer> Buffer,<br>
> +          std::shared_ptr<<wbr>PCHContainerOperations> PCHs,<br>
> +          IntrusiveRefCntPtr<vfs::<wbr>FileSystem> VFS);<br>
> +<br>
> +    ParsedAST(ParsedAST &&Other);<br>
> +    ParsedAST &operator=(ParsedAST &&Other);<br>
> +<br>
> +    ~ParsedAST();<br>
> +<br>
> +    ASTContext &getASTContext();<br>
> +    const ASTContext &getASTContext() const;<br>
> +<br>
> +    Preprocessor &getPreprocessor();<br>
> +    const Preprocessor &getPreprocessor() const;<br>
> +<br>
> +    /// This function returns all top-level decls, including those that come<br>
> +    /// from Preamble. Decls, coming from Preamble, have to be deserialized,<br>
> so<br>
> +    /// this call might be expensive.<br>
> +    ArrayRef<const Decl *> getTopLevelDecls();<br>
> +<br>
> +    const std::vector<DiagWithFixIts> &getDiagnostics() const;<br>
> +<br>
> +  private:<br>
> +    ParsedAST(std::unique_ptr<<wbr>CompilerInstance> Clang,<br>
> +              std::unique_ptr<<wbr>FrontendAction> Action,<br>
> +              std::vector<const Decl *> TopLevelDecls,<br>
> +              std::vector<serialization::<wbr>DeclID> PendingTopLevelDecls,<br>
> +              std::vector<DiagWithFixIts> Diags);<br>
> +<br>
> +  private:<br>
> +    void ensurePreambleDeclsDeserialize<wbr>d();<br>
> +<br>
> +    // We store an "incomplete" FrontendAction (i.e. no EndSourceFile was<br>
> called<br>
> +    // on it) and CompilerInstance used to run it. That way we don't have to<br>
> do<br>
> +    // complex memory management of all Clang structures on our own. (They<br>
> are<br>
> +    // stored in CompilerInstance and cleaned up by<br>
> +    // FrontendAction.EndSourceFile).<br>
> +    std::unique_ptr<<wbr>CompilerInstance> Clang;<br>
> +    std::unique_ptr<<wbr>FrontendAction> Action;<br>
> +<br>
> +    // Data, stored after parsing.<br>
> +    std::vector<DiagWithFixIts> Diags;<br>
> +    std::vector<const Decl *> TopLevelDecls;<br>
> +    std::vector<serialization::<wbr>DeclID> PendingTopLevelDecls;<br>
> +  };<br>
> +<br>
> +  // Store Preamble and all associated data<br>
> +  struct PreambleData {<br>
> +    PreambleData(<wbr>PrecompiledPreamble Preamble,<br>
> +                 std::vector<serialization::<wbr>DeclID> TopLevelDeclIDs,<br>
> +                 std::vector<DiagWithFixIts> Diags);<br>
> +<br>
> +    PrecompiledPreamble Preamble;<br>
> +    std::vector<serialization::<wbr>DeclID> TopLevelDeclIDs;<br>
> +    std::vector<DiagWithFixIts> Diags;<br>
> +  };<br>
> +<br>
> +  SourceLocation getBeginningOfIdentifier(const Position &Pos,<br>
> +                                          const FileEntry *FE) const;<br>
> +<br>
>    Path FileName;<br>
> -  std::unique_ptr<ASTUnit> Unit;<br>
> -  std::shared_ptr<<wbr>PCHContainerOperations> PCHs;<br>
> +  tooling::CompileCommand Command;<br>
><br>
> -  SourceLocation getBeginningOfIdentifier(const Position& Pos, const<br>
> FileEntry* FE) const;<br>
> +  llvm::Optional<PreambleData> Preamble;<br>
> +  llvm::Optional<ParsedAST> Unit;<br>
> +<br>
> +  std::shared_ptr<<wbr>PCHContainerOperations> PCHs;<br>
>  };<br>
><br>
>  } // namespace clangd<br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div>Regards,</div><div>Ilya Biryukov</div></div></div></div></div>
</div>