llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Jacques Pienaar (jpienaar) <details> <summary>Changes</summary> These classes are not specific to clang and useful for other rewriter tools (flagged in previous review). --- Patch is 91.29 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/99770.diff 26 Files Affected: - (removed) clang/include/clang/Rewrite/Core/DeltaTree.h (-50) - (modified) clang/include/clang/Rewrite/Core/HTMLRewrite.h (+7-4) - (removed) clang/include/clang/Rewrite/Core/RewriteRope.h (-223) - (modified) clang/include/clang/Rewrite/Core/Rewriter.h (+10-9) - (modified) clang/lib/ARCMigrate/ARCMT.cpp (+1-1) - (modified) clang/lib/ARCMigrate/ObjCMT.cpp (+1) - (modified) clang/lib/Frontend/Rewrite/FixItRewriter.cpp (+2-1) - (modified) clang/lib/Frontend/Rewrite/HTMLPrint.cpp (+2) - (modified) clang/lib/Frontend/Rewrite/RewriteMacros.cpp (+3-1) - (modified) clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp (+2-1) - (modified) clang/lib/Frontend/Rewrite/RewriteObjC.cpp (+1) - (modified) clang/lib/Rewrite/CMakeLists.txt (-2) - (modified) clang/lib/Rewrite/HTMLRewrite.cpp (+1) - (modified) clang/lib/Rewrite/Rewriter.cpp (+7-102) - (modified) clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp (+2) - (modified) clang/lib/Tooling/Core/Replacement.cpp (+1-1) - (modified) clang/unittests/Rewrite/CMakeLists.txt (-1) - (added) llvm/include/llvm/ADT/DeltaTree.h (+50) - (renamed) llvm/include/llvm/ADT/RewriteBuffer.h (+20-20) - (added) llvm/include/llvm/ADT/RewriteRope.h (+223) - (modified) llvm/lib/Support/CMakeLists.txt (+3) - (renamed) llvm/lib/Support/DeltaTree.cpp (+130-135) - (added) llvm/lib/Support/RewriteBuffer.cpp (+107) - (renamed) llvm/lib/Support/RewriteRope.cpp (+249-258) - (modified) llvm/unittests/ADT/CMakeLists.txt (+1) - (renamed) llvm/unittests/ADT/RewriteBufferTest.cpp (+2-3) ``````````diff diff --git a/clang/include/clang/Rewrite/Core/DeltaTree.h b/clang/include/clang/Rewrite/Core/DeltaTree.h deleted file mode 100644 index e566c92aaff91..0000000000000 --- a/clang/include/clang/Rewrite/Core/DeltaTree.h +++ /dev/null @@ -1,50 +0,0 @@ -//===- DeltaTree.h - B-Tree for Rewrite Delta tracking ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the DeltaTree class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_REWRITE_CORE_DELTATREE_H -#define LLVM_CLANG_REWRITE_CORE_DELTATREE_H - -namespace clang { - - /// DeltaTree - a multiway search tree (BTree) structure with some fancy - /// features. B-Trees are generally more memory and cache efficient than - /// binary trees, because they store multiple keys/values in each node. This - /// implements a key/value mapping from index to delta, and allows fast lookup - /// on index. However, an added (important) bonus is that it can also - /// efficiently tell us the full accumulated delta for a specific file offset - /// as well, without traversing the whole tree. - class DeltaTree { - void *Root; // "DeltaTreeNode *" - - public: - DeltaTree(); - - // Note: Currently we only support copying when the RHS is empty. - DeltaTree(const DeltaTree &RHS); - - DeltaTree &operator=(const DeltaTree &) = delete; - ~DeltaTree(); - - /// getDeltaAt - Return the accumulated delta at the specified file offset. - /// This includes all insertions or delections that occurred *before* the - /// specified file index. - int getDeltaAt(unsigned FileIndex) const; - - /// AddDelta - When a change is made that shifts around the text buffer, - /// this method is used to record that info. It inserts a delta of 'Delta' - /// into the current DeltaTree at offset FileIndex. - void AddDelta(unsigned FileIndex, int Delta); - }; - -} // namespace clang - -#endif // LLVM_CLANG_REWRITE_CORE_DELTATREE_H diff --git a/clang/include/clang/Rewrite/Core/HTMLRewrite.h b/clang/include/clang/Rewrite/Core/HTMLRewrite.h index eecf589632746..9edb514d566b9 100644 --- a/clang/include/clang/Rewrite/Core/HTMLRewrite.h +++ b/clang/include/clang/Rewrite/Core/HTMLRewrite.h @@ -17,10 +17,13 @@ #include "clang/Basic/SourceLocation.h" #include <string> +namespace llvm { +class RewriteBuffer; +} // namespace llvm + namespace clang { class Rewriter; -class RewriteBuffer; class Preprocessor; namespace html { @@ -53,9 +56,9 @@ namespace html { /// HighlightRange - This is the same as the above method, but takes /// decomposed file locations. - void HighlightRange(RewriteBuffer &RB, unsigned B, unsigned E, - const char *BufferStart, - const char *StartTag, const char *EndTag); + void HighlightRange(llvm::RewriteBuffer &RB, unsigned B, unsigned E, + const char *BufferStart, const char *StartTag, + const char *EndTag); /// EscapeText - HTMLize a specified file so that special characters are /// are translated so that they are not interpreted as HTML tags. diff --git a/clang/include/clang/Rewrite/Core/RewriteRope.h b/clang/include/clang/Rewrite/Core/RewriteRope.h deleted file mode 100644 index 73e66e111f574..0000000000000 --- a/clang/include/clang/Rewrite/Core/RewriteRope.h +++ /dev/null @@ -1,223 +0,0 @@ -//===- RewriteRope.h - Rope specialized for rewriter ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the RewriteRope class, which is a powerful string class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H -#define LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H - -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/StringRef.h" -#include <cassert> -#include <cstddef> -#include <iterator> -#include <utility> - -namespace clang { - - //===--------------------------------------------------------------------===// - // RopeRefCountString Class - //===--------------------------------------------------------------------===// - - /// RopeRefCountString - This struct is allocated with 'new char[]' from the - /// heap, and represents a reference counted chunk of string data. When its - /// ref count drops to zero, it is delete[]'d. This is primarily managed - /// through the RopePiece class below. - struct RopeRefCountString { - unsigned RefCount; - char Data[1]; // Variable sized. - - void Retain() { ++RefCount; } - - void Release() { - assert(RefCount > 0 && "Reference count is already zero."); - if (--RefCount == 0) - delete [] (char*)this; - } - }; - - //===--------------------------------------------------------------------===// - // RopePiece Class - //===--------------------------------------------------------------------===// - - /// RopePiece - This class represents a view into a RopeRefCountString object. - /// This allows references to string data to be efficiently chopped up and - /// moved around without having to push around the string data itself. - /// - /// For example, we could have a 1M RopePiece and want to insert something - /// into the middle of it. To do this, we split it into two RopePiece objects - /// that both refer to the same underlying RopeRefCountString (just with - /// different offsets) which is a nice constant time operation. - struct RopePiece { - llvm::IntrusiveRefCntPtr<RopeRefCountString> StrData; - unsigned StartOffs = 0; - unsigned EndOffs = 0; - - RopePiece() = default; - RopePiece(llvm::IntrusiveRefCntPtr<RopeRefCountString> Str, unsigned Start, - unsigned End) - : StrData(std::move(Str)), StartOffs(Start), EndOffs(End) {} - - const char &operator[](unsigned Offset) const { - return StrData->Data[Offset+StartOffs]; - } - char &operator[](unsigned Offset) { - return StrData->Data[Offset+StartOffs]; - } - - unsigned size() const { return EndOffs-StartOffs; } - }; - - //===--------------------------------------------------------------------===// - // RopePieceBTreeIterator Class - //===--------------------------------------------------------------------===// - - /// RopePieceBTreeIterator - This class provides read-only forward iteration - /// over bytes that are in a RopePieceBTree. This first iterates over bytes - /// in a RopePiece, then iterates over RopePiece's in a RopePieceBTreeLeaf, - /// then iterates over RopePieceBTreeLeaf's in a RopePieceBTree. - class RopePieceBTreeIterator { - /// CurNode - The current B+Tree node that we are inspecting. - const void /*RopePieceBTreeLeaf*/ *CurNode = nullptr; - - /// CurPiece - The current RopePiece in the B+Tree node that we're - /// inspecting. - const RopePiece *CurPiece = nullptr; - - /// CurChar - The current byte in the RopePiece we are pointing to. - unsigned CurChar = 0; - - public: - using iterator_category = std::forward_iterator_tag; - using value_type = const char; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - - RopePieceBTreeIterator() = default; - RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N); - - char operator*() const { - return (*CurPiece)[CurChar]; - } - - bool operator==(const RopePieceBTreeIterator &RHS) const { - return CurPiece == RHS.CurPiece && CurChar == RHS.CurChar; - } - bool operator!=(const RopePieceBTreeIterator &RHS) const { - return !operator==(RHS); - } - - RopePieceBTreeIterator& operator++() { // Preincrement - if (CurChar+1 < CurPiece->size()) - ++CurChar; - else - MoveToNextPiece(); - return *this; - } - - RopePieceBTreeIterator operator++(int) { // Postincrement - RopePieceBTreeIterator tmp = *this; ++*this; return tmp; - } - - llvm::StringRef piece() const { - return llvm::StringRef(&(*CurPiece)[0], CurPiece->size()); - } - - void MoveToNextPiece(); - }; - - //===--------------------------------------------------------------------===// - // RopePieceBTree Class - //===--------------------------------------------------------------------===// - - class RopePieceBTree { - void /*RopePieceBTreeNode*/ *Root; - - public: - RopePieceBTree(); - RopePieceBTree(const RopePieceBTree &RHS); - RopePieceBTree &operator=(const RopePieceBTree &) = delete; - ~RopePieceBTree(); - - using iterator = RopePieceBTreeIterator; - - iterator begin() const { return iterator(Root); } - iterator end() const { return iterator(); } - unsigned size() const; - unsigned empty() const { return size() == 0; } - - void clear(); - - void insert(unsigned Offset, const RopePiece &R); - - void erase(unsigned Offset, unsigned NumBytes); - }; - - //===--------------------------------------------------------------------===// - // RewriteRope Class - //===--------------------------------------------------------------------===// - -/// RewriteRope - A powerful string class. This class supports extremely -/// efficient insertions and deletions into the middle of it, even for -/// ridiculously long strings. -class RewriteRope { - RopePieceBTree Chunks; - - /// We allocate space for string data out of a buffer of size AllocChunkSize. - /// This keeps track of how much space is left. - llvm::IntrusiveRefCntPtr<RopeRefCountString> AllocBuffer; - enum { AllocChunkSize = 4080 }; - unsigned AllocOffs = AllocChunkSize; - -public: - RewriteRope() = default; - RewriteRope(const RewriteRope &RHS) : Chunks(RHS.Chunks) {} - - // The copy assignment operator is defined as deleted pending further - // motivation. - RewriteRope &operator=(const RewriteRope &) = delete; - - using iterator = RopePieceBTree::iterator; - using const_iterator = RopePieceBTree::iterator; - - iterator begin() const { return Chunks.begin(); } - iterator end() const { return Chunks.end(); } - unsigned size() const { return Chunks.size(); } - - void clear() { - Chunks.clear(); - } - - void assign(const char *Start, const char *End) { - clear(); - if (Start != End) - Chunks.insert(0, MakeRopeString(Start, End)); - } - - void insert(unsigned Offset, const char *Start, const char *End) { - assert(Offset <= size() && "Invalid position to insert!"); - if (Start == End) return; - Chunks.insert(Offset, MakeRopeString(Start, End)); - } - - void erase(unsigned Offset, unsigned NumBytes) { - assert(Offset+NumBytes <= size() && "Invalid region to erase!"); - if (NumBytes == 0) return; - Chunks.erase(Offset, NumBytes); - } - -private: - RopePiece MakeRopeString(const char *Start, const char *End); -}; - -} // namespace clang - -#endif // LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H diff --git a/clang/include/clang/Rewrite/Core/Rewriter.h b/clang/include/clang/Rewrite/Core/Rewriter.h index c89015e405582..4e96f6fcca919 100644 --- a/clang/include/clang/Rewrite/Core/Rewriter.h +++ b/clang/include/clang/Rewrite/Core/Rewriter.h @@ -16,7 +16,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Rewrite/Core/RewriteBuffer.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/ADT/StringRef.h" #include <map> #include <string> @@ -32,7 +32,7 @@ class SourceManager; class Rewriter { SourceManager *SourceMgr = nullptr; const LangOptions *LangOpts = nullptr; - std::map<FileID, RewriteBuffer> RewriteBuffers; + std::map<FileID, llvm::RewriteBuffer> RewriteBuffers; public: struct RewriteOptions { @@ -49,7 +49,7 @@ class Rewriter { /// /// FIXME: This sometimes corrupts the file's rewrite buffer due to /// incorrect indexing in the implementation (see the FIXME in - /// clang::RewriteBuffer::RemoveText). Moreover, it's inefficient because + /// llvm::RewriteBuffer::RemoveText). Moreover, it's inefficient because /// it must scan the buffer from the beginning to find the start of the /// line. When feasible, it's better for the caller to check for a blank /// line and then, if found, expand the removal range to include it. @@ -62,8 +62,9 @@ class Rewriter { RewriteOptions() {} }; - using buffer_iterator = std::map<FileID, RewriteBuffer>::iterator; - using const_buffer_iterator = std::map<FileID, RewriteBuffer>::const_iterator; + using buffer_iterator = std::map<FileID, llvm::RewriteBuffer>::iterator; + using const_buffer_iterator = + std::map<FileID, llvm::RewriteBuffer>::const_iterator; explicit Rewriter() = default; explicit Rewriter(SourceManager &SM, const LangOptions &LO) @@ -191,13 +192,13 @@ class Rewriter { /// buffer, and allows you to write on it directly. This is useful if you /// want efficient low-level access to apis for scribbling on one specific /// FileID's buffer. - RewriteBuffer &getEditBuffer(FileID FID); + llvm::RewriteBuffer &getEditBuffer(FileID FID); /// getRewriteBufferFor - Return the rewrite buffer for the specified FileID. /// If no modification has been made to it, return null. - const RewriteBuffer *getRewriteBufferFor(FileID FID) const { - std::map<FileID, RewriteBuffer>::const_iterator I = - RewriteBuffers.find(FID); + const llvm::RewriteBuffer *getRewriteBufferFor(FileID FID) const { + std::map<FileID, llvm::RewriteBuffer>::const_iterator I = + RewriteBuffers.find(FID); return I == RewriteBuffers.end() ? nullptr : &I->second; } diff --git a/clang/lib/ARCMigrate/ARCMT.cpp b/clang/lib/ARCMigrate/ARCMT.cpp index 5835559bff6b7..1a8a200f2fc19 100644 --- a/clang/lib/ARCMigrate/ARCMT.cpp +++ b/clang/lib/ARCMigrate/ARCMT.cpp @@ -596,7 +596,7 @@ bool MigrationProcess::applyTransform(TransformFn trans, for (Rewriter::buffer_iterator I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) { FileID FID = I->first; - RewriteBuffer &buf = I->second; + llvm::RewriteBuffer &buf = I->second; OptionalFileEntryRef file = Ctx.getSourceManager().getFileEntryRefForID(FID); assert(file); diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index 4357c8e3f09a5..c1bc7c762088f 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -36,6 +36,7 @@ using namespace clang; using namespace arcmt; using namespace ento; +using llvm::RewriteBuffer; namespace { diff --git a/clang/lib/Frontend/Rewrite/FixItRewriter.cpp b/clang/lib/Frontend/Rewrite/FixItRewriter.cpp index 567bac576adb4..44dfaf20eae73 100644 --- a/clang/lib/Frontend/Rewrite/FixItRewriter.cpp +++ b/clang/lib/Frontend/Rewrite/FixItRewriter.cpp @@ -21,8 +21,8 @@ #include "clang/Edit/Commit.h" #include "clang/Edit/EditsReceiver.h" #include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Rewrite/Core/RewriteBuffer.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" @@ -33,6 +33,7 @@ #include <utility> using namespace clang; +using llvm::RewriteBuffer; FixItRewriter::FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const LangOptions &LangOpts, diff --git a/clang/lib/Frontend/Rewrite/HTMLPrint.cpp b/clang/lib/Frontend/Rewrite/HTMLPrint.cpp index 69baa8f591088..5cce193ed1c4f 100644 --- a/clang/lib/Frontend/Rewrite/HTMLPrint.cpp +++ b/clang/lib/Frontend/Rewrite/HTMLPrint.cpp @@ -20,8 +20,10 @@ #include "clang/Rewrite/Core/HTMLRewrite.h" #include "clang/Rewrite/Core/Rewriter.h" #include "clang/Rewrite/Frontend/ASTConsumers.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/Support/raw_ostream.h" using namespace clang; +using llvm::RewriteBuffer; //===----------------------------------------------------------------------===// // Functional HTML pretty-printing. diff --git a/clang/lib/Frontend/Rewrite/RewriteMacros.cpp b/clang/lib/Frontend/Rewrite/RewriteMacros.cpp index 5701b271aff10..b533cabe97f5e 100644 --- a/clang/lib/Frontend/Rewrite/RewriteMacros.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteMacros.cpp @@ -11,16 +11,18 @@ // //===----------------------------------------------------------------------===// -#include "clang/Rewrite/Frontend/Rewriters.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Preprocessor.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Rewrite/Frontend/Rewriters.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include <cstdio> #include <memory> using namespace clang; +using llvm::RewriteBuffer; /// isSameToken - Return true if the two specified tokens start have the same /// content. diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp index 3849e4040b53a..f618c536b5f3c 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Rewrite/Frontend/ASTConsumers.h" #include "clang/AST/AST.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/Attr.h" @@ -23,6 +22,7 @@ #include "clang/Config/config.h" #include "clang/Lex/Lexer.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Rewrite/Frontend/ASTConsumers.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -34,6 +34,7 @@ #if CLANG_ENABLE_OBJC_REWRITER using namespace clang; +using llvm::RewriteBuffer; using llvm::utostr; namespace { diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp index bf5176a2b6fb2..9db6ddbf0b890 100644 --- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -32,6 +32,7 @@ #if CLANG_ENABLE_OBJC_REWRITER using namespace clang; +using llvm::RewriteBuffer; using llvm::utostr; namespace { diff --git a/clang/lib/Rewrite/CMakeLists.txt b/clang/lib/Rewrite/CMakeLists.txt index 16550b1b710ef..93ecb3c835260 100644 --- a/clang/lib/Rewrite/CMakeLists.txt +++ b/clang/lib/Rewrite/CMakeLists.txt @@ -3,9 +3,7 @@ set(LLVM_LINK_COMPONENTS ) add_clang_library(clangRewrite - DeltaTree.cpp HTMLRewrite.cpp - RewriteRope.cpp Rewriter.cpp TokenRewriter.cpp diff --git a/clang/lib/Rewrite/HTMLRewrite.cpp b/clang/lib/Rewrite/HTMLRewrite.cpp index a96ca0764ae73..c75835df2c98e 100644 --- a/clang/lib/Rewrite/HTMLRewrite.cpp +++ b/clang/lib/Rewrite/HTMLRewrite.cpp @@ -16,6 +16,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Lex/TokenConcatenation.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/ADT/RewriteBuffer.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" diff --git a/clang/lib/Rewrite/Rewriter.cpp b/clang/lib/Rewrite/Rewriter.cpp index 0e6ae36506446..68cf797f97905 100644 --- a/clang/lib/Rewrite/Rewriter.cpp +++ b/clang/lib/Rewrite/Rewriter.cpp @@ -17,8 +17,8 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" -#include "clang/Rewrite/Core/RewriteBuffer.h" -#include "clang/Rewrite/Core/RewriteRope.h" +#include "llvm/ADT/RewriteBuffer.h" +#include "llvm/ADT/RewriteRope.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -29,113 +29,18 @@ #include <utility> using namespace clang; +using llvm::RewriteBuffer; -raw_ostream &RewriteBuffer::write(raw_ostream &os) const { - // Walk RewriteRope chunks efficiently using MoveToNextPiece() instead of the - // character iterator. - for (RopePieceBTreeIterator... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/99770 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits