[clang-tools-extra] r332362 - [clangd] Remove LSP command-based #include insertion.
Eric Liu via cfe-commits
cfe-commits at lists.llvm.org
Tue May 15 08:23:53 PDT 2018
Author: ioeric
Date: Tue May 15 08:23:53 2018
New Revision: 332362
URL: http://llvm.org/viewvc/llvm-project?rev=332362&view=rev
Log:
[clangd] Remove LSP command-based #include insertion.
Summary:
clangd will populate #include insertions as addtionalEdits in completion items.
The code completion tests in ClangdServerTest will be added back in D46497.
Reviewers: ilya-biryukov, sammccall
Reviewed By: ilya-biryukov
Subscribers: klimek, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D46676
Removed:
clang-tools-extra/trunk/test/clangd/insert-include.test
Modified:
clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
clang-tools-extra/trunk/clangd/ClangdServer.cpp
clang-tools-extra/trunk/clangd/ClangdServer.h
clang-tools-extra/trunk/clangd/CodeComplete.cpp
clang-tools-extra/trunk/clangd/Protocol.cpp
clang-tools-extra/trunk/clangd/Protocol.h
clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test
clang-tools-extra/trunk/test/clangd/initialize-params.test
clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=332362&r1=332361&r2=332362&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Tue May 15 08:23:53 2018
@@ -115,9 +115,7 @@ void ClangdLSPServer::onInitialize(Initi
{"workspaceSymbolProvider", true},
{"executeCommandProvider",
json::obj{
- {"commands",
- {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND,
- ExecuteCommandParams::CLANGD_INSERT_HEADER_INCLUDE}},
+ {"commands", {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND}},
}},
}}}});
}
@@ -190,42 +188,6 @@ void ClangdLSPServer::onCommand(ExecuteC
reply("Fix applied.");
ApplyEdit(*Params.workspaceEdit);
- } else if (Params.command ==
- ExecuteCommandParams::CLANGD_INSERT_HEADER_INCLUDE) {
- auto &FileURI = Params.includeInsertion->textDocument.uri;
- auto Code = DraftMgr.getDraft(FileURI.file());
- if (!Code)
- return replyError(ErrorCode::InvalidParams,
- ("command " +
- ExecuteCommandParams::CLANGD_INSERT_HEADER_INCLUDE +
- " called on non-added file " + FileURI.file())
- .str());
- llvm::StringRef DeclaringHeader = Params.includeInsertion->declaringHeader;
- if (DeclaringHeader.empty())
- return replyError(
- ErrorCode::InvalidParams,
- "declaringHeader must be provided for include insertion.");
- llvm::StringRef PreferredHeader = Params.includeInsertion->preferredHeader;
- auto Replaces = Server.insertInclude(
- FileURI.file(), *Code, DeclaringHeader,
- PreferredHeader.empty() ? DeclaringHeader : PreferredHeader);
- if (!Replaces) {
- std::string ErrMsg =
- ("Failed to generate include insertion edits for adding " +
- DeclaringHeader + " (" + PreferredHeader + ") into " +
- FileURI.file())
- .str();
- log(ErrMsg + ":" + llvm::toString(Replaces.takeError()));
- replyError(ErrorCode::InternalError, ErrMsg);
- return;
- }
- auto Edits = replacementsToEdits(*Code, *Replaces);
- WorkspaceEdit WE;
- WE.changes = {{FileURI.uri(), Edits}};
-
- reply(("Inserted header " + DeclaringHeader + " (" + PreferredHeader + ")")
- .str());
- ApplyEdit(std::move(WE));
} else {
// We should not get here because ExecuteCommandParams would not have
// parsed in the first place and this handler should not be called. But if
Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=332362&r1=332361&r2=332362&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Tue May 15 08:23:53 2018
@@ -272,66 +272,6 @@ void ClangdServer::rename(PathRef File,
"Rename", File, Bind(Action, File.str(), NewName.str(), std::move(CB)));
}
-/// Creates a `HeaderFile` from \p Header which can be either a URI or a literal
-/// include.
-static llvm::Expected<HeaderFile> toHeaderFile(StringRef Header,
- llvm::StringRef HintPath) {
- if (isLiteralInclude(Header))
- return HeaderFile{Header.str(), /*Verbatim=*/true};
- auto U = URI::parse(Header);
- if (!U)
- return U.takeError();
-
- auto IncludePath = URI::includeSpelling(*U);
- if (!IncludePath)
- return IncludePath.takeError();
- if (!IncludePath->empty())
- return HeaderFile{std::move(*IncludePath), /*Verbatim=*/true};
-
- auto Resolved = URI::resolve(*U, HintPath);
- if (!Resolved)
- return Resolved.takeError();
- return HeaderFile{std::move(*Resolved), /*Verbatim=*/false};
-}
-
-Expected<tooling::Replacements>
-ClangdServer::insertInclude(PathRef File, StringRef Code,
- StringRef DeclaringHeader,
- StringRef InsertedHeader) {
- assert(!DeclaringHeader.empty() && !InsertedHeader.empty());
- std::string ToInclude;
- auto ResolvedOrginal = toHeaderFile(DeclaringHeader, File);
- if (!ResolvedOrginal)
- return ResolvedOrginal.takeError();
- auto ResolvedPreferred = toHeaderFile(InsertedHeader, File);
- if (!ResolvedPreferred)
- return ResolvedPreferred.takeError();
- tooling::CompileCommand CompileCommand = CompileArgs.getCompileCommand(File);
- auto Include =
- calculateIncludePath(File, Code, *ResolvedOrginal, *ResolvedPreferred,
- CompileCommand, FSProvider.getFileSystem());
- if (!Include)
- return Include.takeError();
- if (Include->empty())
- return tooling::Replacements();
- ToInclude = std::move(*Include);
-
- auto Style = format::getStyle("file", File, "llvm");
- if (!Style) {
- llvm::consumeError(Style.takeError());
- // FIXME(ioeric): needs more consistent style support in clangd server.
- Style = format::getLLVMStyle();
- }
- // Replacement with offset UINT_MAX and length 0 will be treated as include
- // insertion.
- tooling::Replacement R(File, /*Offset=*/UINT_MAX, 0, "#include " + ToInclude);
- auto Replaces =
- format::cleanupAroundReplacements(Code, tooling::Replacements(R), *Style);
- if (!Replaces)
- return Replaces;
- return formatReplacements(Code, *Replaces, *Style);
-}
-
void ClangdServer::dumpAST(PathRef File,
UniqueFunction<void(std::string)> Callback) {
auto Action = [](decltype(Callback) Callback,
Modified: clang-tools-extra/trunk/clangd/ClangdServer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=332362&r1=332361&r2=332362&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.h Tue May 15 08:23:53 2018
@@ -179,22 +179,6 @@ public:
void rename(PathRef File, Position Pos, llvm::StringRef NewName,
Callback<std::vector<tooling::Replacement>> CB);
- /// Inserts a new #include into \p File, if it's not present in \p Code.
- ///
- /// \p DeclaringHeader The original header corresponding to this insertion
- /// e.g. the header that declared a symbol. This can be either a URI or a
- /// literal string quoted with <> or "" that can be #included directly.
- /// \p InsertedHeader The preferred header to be inserted. This may be
- /// different from \p DeclaringHeader as a header file can have a different
- /// canonical include. This can be either a URI or a literal string quoted
- /// with <> or "" that can be #included directly.
- ///
- /// Both OriginalHeader and InsertedHeader will be considered to determine
- /// whether an include needs to be added.
- Expected<tooling::Replacements> insertInclude(PathRef File, StringRef Code,
- StringRef DeclaringHeader,
- StringRef InsertedHeader);
-
/// Only for testing purposes.
/// Waits until all requests to worker thread are finished and dumps AST for
/// \p File. \p File must be in the list of added documents.
Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.cpp?rev=332362&r1=332361&r2=332362&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CodeComplete.cpp (original)
+++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Tue May 15 08:23:53 2018
@@ -289,27 +289,6 @@ struct CompletionCandidate {
I.documentation = D->Documentation;
if (I.detail.empty())
I.detail = D->CompletionDetail;
- // FIXME: delay creating include insertion command to
- // "completionItem/resolve", when it is supported
- if (!D->IncludeHeader.empty()) {
- // LSP favors additionalTextEdits over command. But we are still using
- // command here because it would be expensive to calculate #include
- // insertion edits for all candidates, and the include insertion edit
- // is unlikely to conflict with the code completion edits.
- Command Cmd;
- // Command title is not added since this is not a user-facing command.
- Cmd.command = ExecuteCommandParams::CLANGD_INSERT_HEADER_INCLUDE;
- IncludeInsertion Insertion;
- // Fallback to canonical header if declaration location is invalid.
- Insertion.declaringHeader =
- IndexResult->CanonicalDeclaration.FileURI.empty()
- ? D->IncludeHeader
- : IndexResult->CanonicalDeclaration.FileURI;
- Insertion.preferredHeader = D->IncludeHeader;
- Insertion.textDocument.uri = URIForFile(FileName);
- Cmd.includeInsertion = std::move(Insertion);
- I.command = std::move(Cmd);
- }
}
}
I.scoreInfo = Scores;
Modified: clang-tools-extra/trunk/clangd/Protocol.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.cpp?rev=332362&r1=332361&r2=332362&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.cpp (original)
+++ clang-tools-extra/trunk/clangd/Protocol.cpp Tue May 15 08:23:53 2018
@@ -390,9 +390,6 @@ bool fromJSON(const json::Expr &Params,
const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND =
"clangd.applyFix";
-const llvm::StringLiteral ExecuteCommandParams::CLANGD_INSERT_HEADER_INCLUDE =
- "clangd.insertInclude";
-
bool fromJSON(const json::Expr &Params, ExecuteCommandParams &R) {
json::ObjectMapper O(Params);
if (!O || !O.map("command", R.command))
@@ -402,9 +399,6 @@ bool fromJSON(const json::Expr &Params,
if (R.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND) {
return Args && Args->size() == 1 &&
fromJSON(Args->front(), R.workspaceEdit);
- } else if (R.command == ExecuteCommandParams::CLANGD_INSERT_HEADER_INCLUDE) {
- return Args && Args->size() == 1 &&
- fromJSON(Args->front(), R.includeInsertion);
}
return false; // Unrecognized command.
}
@@ -433,8 +427,6 @@ json::Expr toJSON(const Command &C) {
auto Cmd = json::obj{{"title", C.title}, {"command", C.command}};
if (C.workspaceEdit)
Cmd["arguments"] = {*C.workspaceEdit};
- else if (C.includeInsertion)
- Cmd["arguments"] = {*C.includeInsertion};
return std::move(Cmd);
}
@@ -447,18 +439,6 @@ json::Expr toJSON(const WorkspaceEdit &W
return json::obj{{"changes", std::move(FileChanges)}};
}
-bool fromJSON(const json::Expr &II, IncludeInsertion &R) {
- json::ObjectMapper O(II);
- return O && O.map("textDocument", R.textDocument) &&
- O.map("declaringHeader", R.declaringHeader) &&
- O.map("preferredHeader", R.preferredHeader);
-}
-json::Expr toJSON(const IncludeInsertion &II) {
- return json::obj{{"textDocument", II.textDocument},
- {"declaringHeader", II.declaringHeader},
- {"preferredHeader", II.preferredHeader}};
-}
-
json::Expr toJSON(const ApplyWorkspaceEditParams &Params) {
return json::obj{{"edit", Params.edit}};
}
@@ -519,8 +499,6 @@ json::Expr toJSON(const CompletionItem &
Result["textEdit"] = *CI.textEdit;
if (!CI.additionalTextEdits.empty())
Result["additionalTextEdits"] = json::ary(CI.additionalTextEdits);
- if (CI.command)
- Result["command"] = *CI.command;
return std::move(Result);
}
Modified: clang-tools-extra/trunk/clangd/Protocol.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.h?rev=332362&r1=332361&r2=332362&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.h (original)
+++ clang-tools-extra/trunk/clangd/Protocol.h Tue May 15 08:23:53 2018
@@ -538,26 +538,6 @@ struct WorkspaceEdit {
bool fromJSON(const json::Expr &, WorkspaceEdit &);
json::Expr toJSON(const WorkspaceEdit &WE);
-struct IncludeInsertion {
- /// The document in which the command was invoked.
- /// If either originalHeader or preferredHeader has been (directly) included
- /// in the current file, no new include will be inserted.
- TextDocumentIdentifier textDocument;
-
- /// The declaring header corresponding to this insertion e.g. the header that
- /// declares a symbol. This could be either a URI or a literal string quoted
- /// with <> or "" that can be #included directly.
- std::string declaringHeader;
- /// The preferred header to be inserted. This may be different from
- /// originalHeader as a header file can have a different canonical include.
- /// This could be either a URI or a literal string quoted with <> or "" that
- /// can be #included directly. If empty, declaringHeader is used to calculate
- /// the #include path.
- std::string preferredHeader;
-};
-bool fromJSON(const json::Expr &, IncludeInsertion &);
-json::Expr toJSON(const IncludeInsertion &II);
-
/// Exact commands are not specified in the protocol so we define the
/// ones supported by Clangd here. The protocol specifies the command arguments
/// to be "any[]" but to make this safer and more manageable, each command we
@@ -569,16 +549,12 @@ json::Expr toJSON(const IncludeInsertion
struct ExecuteCommandParams {
// Command to apply fix-its. Uses WorkspaceEdit as argument.
const static llvm::StringLiteral CLANGD_APPLY_FIX_COMMAND;
- // Command to insert an #include into code.
- const static llvm::StringLiteral CLANGD_INSERT_HEADER_INCLUDE;
/// The command identifier, e.g. CLANGD_APPLY_FIX_COMMAND
std::string command;
// Arguments
llvm::Optional<WorkspaceEdit> workspaceEdit;
-
- llvm::Optional<IncludeInsertion> includeInsertion;
};
bool fromJSON(const json::Expr &, ExecuteCommandParams &);
@@ -750,7 +726,6 @@ struct CompletionItem {
/// themselves.
std::vector<TextEdit> additionalTextEdits;
- llvm::Optional<Command> command;
// TODO(krasimir): The following optional fields defined by the language
// server protocol are unsupported:
//
Modified: clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test?rev=332362&r1=332361&r2=332362&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test (original)
+++ clang-tools-extra/trunk/test/clangd/initialize-params-invalid.test Tue May 15 08:23:53 2018
@@ -24,8 +24,7 @@
# CHECK-NEXT: "documentRangeFormattingProvider": true,
# CHECK-NEXT: "executeCommandProvider": {
# CHECK-NEXT: "commands": [
-# CHECK-NEXT: "clangd.applyFix",
-# CHECK-NEXT: "clangd.insertInclude"
+# CHECK-NEXT: "clangd.applyFix"
# CHECK-NEXT: ]
# CHECK-NEXT: },
# CHECK-NEXT: "hoverProvider": true,
Modified: clang-tools-extra/trunk/test/clangd/initialize-params.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/initialize-params.test?rev=332362&r1=332361&r2=332362&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clangd/initialize-params.test (original)
+++ clang-tools-extra/trunk/test/clangd/initialize-params.test Tue May 15 08:23:53 2018
@@ -24,8 +24,7 @@
# CHECK-NEXT: "documentRangeFormattingProvider": true,
# CHECK-NEXT: "executeCommandProvider": {
# CHECK-NEXT: "commands": [
-# CHECK-NEXT: "clangd.applyFix",
-# CHECK-NEXT: "clangd.insertInclude"
+# CHECK-NEXT: "clangd.applyFix"
# CHECK-NEXT: ]
# CHECK-NEXT: },
# CHECK-NEXT: "hoverProvider": true,
Removed: clang-tools-extra/trunk/test/clangd/insert-include.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/insert-include.test?rev=332361&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clangd/insert-include.test (original)
+++ clang-tools-extra/trunk/test/clangd/insert-include.test (removed)
@@ -1,36 +0,0 @@
-# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
-# RUN: clangd -lit-test -pch-storage=memory < %s | FileCheck -strict-whitespace %s
-{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
----
-{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void f() {}"}}}
----
-{"jsonrpc":"2.0","id":3,"method":"workspace/executeCommand","params":{"arguments":[{"declaringHeader":"\"/usr/include/bits/vector\"", "preferredHeader":"<vector>","textDocument":{"uri":"test:///main.cpp"}}],"command":"clangd.insertInclude"}}
-# CHECK: "id": 3,
-# CHECK-NEXT: "jsonrpc": "2.0",
-# CHECK-NEXT: "result": "Inserted header \"/usr/include/bits/vector\" (<vector>)"
-# CHECK-NEXT: }
-# CHECK: "method": "workspace/applyEdit",
-# CHECK-NEXT: "params": {
-# CHECK-NEXT: "edit": {
-# CHECK-NEXT: "changes": {
-# CHECK-NEXT: "file://{{.*}}/main.cpp": [
-# CHECK-NEXT: {
-# CHECK-NEXT: "newText": "#include <vector>\n",
-# CHECK-NEXT: "range": {
-# CHECK-NEXT: "end": {
-# CHECK-NEXT: "character": 0,
-# CHECK-NEXT: "line": 0
-# CHECK-NEXT: },
-# CHECK-NEXT: "start": {
-# CHECK-NEXT: "character": 0,
-# CHECK-NEXT: "line": 0
-# CHECK-NEXT: }
-# CHECK-NEXT: }
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-# CHECK-NEXT: }
-# CHECK-NEXT: }
-# CHECK-NEXT: }
-# CHECK-NEXT: }
----
-{"jsonrpc":"2.0","id":4,"method":"shutdown"}
Modified: clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp?rev=332362&r1=332361&r2=332362&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp Tue May 15 08:23:53 2018
@@ -938,67 +938,6 @@ int d;
ASSERT_EQ(DiagConsumer.Count, 2); // Sanity check - we actually ran both?
}
-TEST_F(ClangdVFSTest, InsertIncludes) {
- MockFSProvider FS;
- ErrorCheckingDiagConsumer DiagConsumer;
- MockCompilationDatabase CDB;
- std::string SearchDirArg = (llvm::Twine("-I") + testRoot()).str();
- CDB.ExtraClangFlags.insert(CDB.ExtraClangFlags.end(), {SearchDirArg.c_str()});
- ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
-
- auto FooCpp = testPath("foo.cpp");
- const auto Code = R"cpp(
-#include "x.h"
-#include "z.h"
-
-void f() {}
-)cpp";
- FS.Files[FooCpp] = Code;
- runAddDocument(Server, FooCpp, Code);
-
- auto ChangedCode = [&](llvm::StringRef Original, llvm::StringRef Preferred) {
- auto Replaces = Server.insertInclude(
- FooCpp, Code, Original, Preferred.empty() ? Original : Preferred);
- EXPECT_TRUE(static_cast<bool>(Replaces));
- auto Changed = tooling::applyAllReplacements(Code, *Replaces);
- EXPECT_TRUE(static_cast<bool>(Changed));
- return *Changed;
- };
- auto Inserted = [&](llvm::StringRef Original, llvm::StringRef Preferred,
- llvm::StringRef Expected) {
- return llvm::StringRef(ChangedCode(Original, Preferred))
- .contains((llvm::Twine("#include ") + Expected + "").str());
- };
-
- EXPECT_TRUE(Inserted("\"y.h\"", /*Preferred=*/"", "\"y.h\""));
- EXPECT_TRUE(Inserted("\"y.h\"", /*Preferred=*/"\"Y.h\"", "\"Y.h\""));
- EXPECT_TRUE(Inserted("<string>", /*Preferred=*/"", "<string>"));
- EXPECT_TRUE(Inserted("<string>", /*Preferred=*/"", "<string>"));
-
- std::string OriginalHeader = URI::createFile(testPath("y.h")).toString();
- std::string PreferredHeader = URI::createFile(testPath("Y.h")).toString();
- EXPECT_TRUE(Inserted(OriginalHeader,
- /*Preferred=*/"", "\"y.h\""));
- EXPECT_TRUE(Inserted(OriginalHeader,
- /*Preferred=*/"<Y.h>", "<Y.h>"));
- EXPECT_TRUE(Inserted(OriginalHeader, PreferredHeader, "\"Y.h\""));
- EXPECT_TRUE(Inserted("<y.h>", PreferredHeader, "\"Y.h\""));
- auto TestURIHeader =
- URI::parse(llvm::formatv("{0}:///x/y/z.h", ClangdTestScheme).str());
- EXPECT_TRUE(static_cast<bool>(TestURIHeader));
- EXPECT_TRUE(Inserted(TestURIHeader->toString(), "", "\"x/y/z.h\""));
-
- // Check that includes are sorted.
- const auto Expected = R"cpp(
-#include "x.h"
-#include "y.h"
-#include "z.h"
-
-void f() {}
-)cpp";
- EXPECT_EQ(Expected, ChangedCode("\"y.h\"", /*Preferred=*/""));
-}
-
TEST_F(ClangdVFSTest, FormatCode) {
MockFSProvider FS;
ErrorCheckingDiagConsumer DiagConsumer;
More information about the cfe-commits
mailing list