aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Basic/SourceManager.cpp
AgeCommit message (Collapse)AuthorFilesLines
2023-09-28[clang] NFCI: Use `FileEntryRef` in `SourceManager::setFileIsTransient()`Jan Svoboda1-2/+2
2023-09-28[clang][Parser][NFC] Fix a doc comment mishapTimm Bäder1-1/+1
2023-09-13[clang] NFCI: Use `FileEntryRef` in `SrcMgr::ContentCache`Jan Svoboda1-1/+1
2023-09-08Reapply "[clang] NFCI: Adopt `SourceManager::getFileEntryRefForID()`"Jan Svoboda1-1/+1
This reapplies ddbcc10b9e26b18f6a70e23d0611b9da75ffa52f, except for a tiny part that was reverted separately: 65331da0032ab4253a4bc0ddcb2da67664bd86a9. That will be reapplied later on, since it turned out to be more involved. This commit is enabled by 5523fefb01c282c4cbcaf6314a9aaf658c6c145f and f0f548a65a215c450d956dbcedb03656449705b9, specifically the part that makes 'clang-tidy/checkers/misc/header-include-cycle.cpp' separator agnostic.
2023-09-06Revert "[clang] NFCI: Adopt `SourceManager::getFileEntryRefForID()`"Jan Svoboda1-1/+1
This reverts commit ddbcc10b9e26b18f6a70e23d0611b9da75ffa52f. The 'clang-tidy/checkers/misc/header-include-cycle.cpp' test started failing on Windows: https://lab.llvm.org/buildbot/#/builders/216/builds/26855.
2023-09-06[clang] NFCI: Adopt `SourceManager::getFileEntryRefForID()`Jan Svoboda1-1/+1
This commit replaces some calls to the deprecated `FileEntry::getName()` with `FileEntryRef::getName()` by swapping current usages of `SourceManager::getFileEntryForID()` with `SourceManager::getFileEntryRefForID()`. This lowers the number of usages of the deprecated `FileEntry::getName()` from 95 to 50.
2023-05-24LLVM_FALLTHROUGH => [[fallthrough]]. NFCCraig Topper1-1/+1
Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D150996
2023-01-28Use llvm::count{lr}_{zero,one} (NFC)Kazu Hirata1-2/+1
2023-01-14[clang] Remove remaining uses of llvm::Optional (NFC)Kazu Hirata1-1/+0
This patch removes several "using" declarations and #include "llvm/ADT/Optional.h". This is part of an effort to migrate from llvm::Optional to std::optional: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2023-01-14[clang] Use std::optional instead of llvm::Optional (NFC)Kazu Hirata1-12/+12
This patch replaces (llvm::|)Optional< with std::optional<. I'll post a separate patch to remove #include "llvm/ADT/Optional.h". This is part of an effort to migrate from llvm::Optional to std::optional: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2023-01-14[clang] Add #include <optional> (NFC)Kazu Hirata1-0/+1
This patch adds #include <optional> to those files containing llvm::Optional<...> or Optional<...>. I'll post a separate patch to actually replace llvm::Optional with std::optional. This is part of an effort to migrate from llvm::Optional to std::optional: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-20[Clang] Prepare for llvm::Optional becoming std::optional.Benjamin Kramer1-2/+2
The needed tweaks are mostly trivial, the one nasty bit is Clang's usage of OptionalStorage. To keep this working old Optional stays around as clang::CustomizableOptional, with the default Storage removed. Optional<File/DirectoryEntryRef> is replaced with a typedef. I tested this with GCC 7.5, the oldest supported GCC I had around. Differential Revision: https://reviews.llvm.org/D140332
2022-12-18Revert "[clang] Convert OptionalFileEntryRefDegradesToFileEntryPtr to ↵Krzysztof Parzyszek1-3/+2
std::optional" This reverts commit 8f0df9f3bbc6d7f3d5cbfd955c5ee4404c53a75d. The Optional*RefDegradesTo*EntryPtr types want to keep the same size as the underlying type, which std::optional doesn't guarantee. For use with llvm::Optional, they define their own storage class, and there is no way to do that in std::optional. On top of that, that commit broke builds with older GCCs, where std::optional was not trivially copyable (static_assert in the clang sources was failing).
2022-12-17[clang] Convert OptionalFileEntryRefDegradesToFileEntryPtr to std::optionalKrzysztof Parzyszek1-2/+3
2022-12-10Don't include None.h (NFC)Kazu Hirata1-1/+0
I've converted all known uses of None to std::nullopt, so we no longer need to include None.h. This is part of an effort to migrate from llvm::Optional to std::optional: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-04Correct typo introduced in f607884a04b0ca06951227a01d00bc59b948d337serge-sans-paille1-1/+1
Fix #59321
2022-12-03[Basic] Use std::nullopt instead of None (NFC)Kazu Hirata1-11/+11
This patch mechanically replaces None with std::nullopt where the compiler would warn if None were deprecated. The intent is to reduce the amount of manual work required in migrating from Optional to std::optional. This is part of an effort to migrate from llvm::Optional to std::optional: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-11-30[Basic] Fix a warningKazu Hirata1-1/+1
This patch fixes: clang/lib/Basic/SourceManager.cpp:1292:19: error: comparison of integers of different signs: 'long' and 'unsigned long' [-Werror,-Wsign-compare]
2022-11-30[clang] Speedup LineOffsetMapping::getserge-sans-paille1-23/+25
LineOffsetMapping::get is a critical function that consistently appears in the top 5 more computation intensive functions when running the preprocessor. This change brings consistent speedup of ~.5% on, preprocessing time, see https://llvm-compile-time-tracker.com/compare.php?from=0745b0c0354a0c8e1fefb68a3876d15db6c2e27a&to=460f3f04dac025e6952d78fce104a88151508a29&stat=instructions:u for detailed statistics. Differential Revision: https://reviews.llvm.org/D138474
2022-11-16When we run out of source locations, try to produce useful informationRichard Smith1-0/+91
indicating why we ran out.
2022-11-08Fix duplicate word typos; NFCRageking81-1/+1
This revision fixes typos where there are 2 consecutive words which are duplicated. There should be no code changes in this revision (only changes to comments and docs). Do let me know if there are any undesirable changes in this revision. Thanks.
2022-10-18Fix incorrect check for running out of source locations.Paul Pluzhnikov1-1/+3
When CurrentLoadedOffset is less than TotalSize, current code will trigger unsigned overflow and will not return an "allocation failed" indicator. Google ref: b/248613299 Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D135192
2022-10-15[clang] Fix a warningKazu Hirata1-4/+5
This patch fixes: clang/lib/Basic/SourceManager.cpp:2131:72: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
2022-10-07[SourceManager] Fix the incorrect counting stats in getFileIDLoaded.Haojian Wu1-2/+0
We were double-counting the number of binary search FileID scans.
2022-10-07[SourceManager] Improve getFileIDLocal.Haojian Wu1-20/+17
Prune the search space -- If we know offset(LastFileIDLookup) < SearchOffset, we can prune the initial binary-search range from [0, end) to [LastFileIDlookup, end). It reduces the binary search scan by ~30%. SemaExpr.cpp: 1393437 -> 1035426 FindTarget.cpp: 1275930 -> 920087 Linux kernel: getFileIDLocal: 2.45% -> 2.15% Differential Revision: https://reviews.llvm.org/D135132
2022-10-06[SourceManager] Improve getFileIDLoaded.Haojian Wu1-16/+18
Similar to getFileIDLocal patch, but for the version for load module. Test with clangd (building AST with preamble), FileID scans in binary search is reduced: SemaExpr.cpp: 142K -> 137K (-3%) FindTarget.cpp: 368K -> 343K (-6%) Differential Revision: https://reviews.llvm.org/D135258
2022-10-05[clang] Update ModuleMap::getModuleMapFile* to use FileEntryRefBen Langmuir1-5/+8
Update SourceManager::ContentCache::OrigEntry to keep the original FileEntryRef, and use that to enable ModuleMap::getModuleMapFile* to return the original FileEntryRef. This change should be NFC for most users of SourceManager::ContentCache, but it could affect behaviour for users of getNameAsRequested such as in compileModuleImpl. I have not found a way to detect that difference without additional functional changes, other than incidental cases like changes from / to \ on Windows so there is no new test. Differential Revision: https://reviews.llvm.org/D135220
2022-10-05Fix SourceManager::isBeforeInTranslationUnit bug with token-pastingSam McCall1-28/+49
isBeforeInTranslationUnit compares SourceLocations across FileIDs by mapping them onto a common ancestor file, following include/expansion edges. It is possible to get a tie in the common ancestor, because multiple "chunks" of a macro arg will expand to the same macro param token in the body: #define ID(X) X #define TWO 2 ID(1 TWO) Here two FileIDs both expand into `X` in ID's expansion: - one containing `1` and spelled on line 3 - one containing `2` and spelled by the macro expansion of TWO isBeforeInTranslationUnit breaks this tie by comparing the two FileIDs: the one "on the left" is always created first and is numerically smaller. This seems correct so far. Prior to this patch it also takes a shortcut (unclear if intentionally). Instead of comparing the two FileIDs that directly expand to the same location, it compares the original FileIDs being compared. These may not be the same if there are multiple macro expansions in between. This *almost* always yields the right answer, because macro expansion yields "trees" of FileIDs allocated in a contiguous range: when comparing tree A to tree B, it doesn't matter what representative you pick. However, the splitting of >> tokens is modeled as macro expansion (as if the first '>' was a macro that expands to a '>' spelled a scratch buffer). This splitting occurs retroactively when parsing, so the FileID allocated is larger than expected if it were a real macro expansion performed during lexing. As a result, macro tree A can be on the left of tree B, and yet contain a token-split FileID whose numeric value is *greator* than those in B. In this case the tiebreak gives the wrong answer. Concretely: #define ID(X) X template <typename> class S{}; ID( ID(S<S<int>> x); int y; ) Given Greater = (typeloc of S<int>).getEndLoc(); Y = (decl of y).getLocation(); isBeforeInTranslationUnit(Greater, Y) should return true, but returns false. Here the common FileID of (Greater, Y) is the body of the outer ID expansion, and they both expand to X within it. With the current tiebreak rules, we compare the FileID of Greater (a split) to the FileID of Y (a macro arg expansion into X of the outer ID). The former is larger because the token split occurred relatively late. This patch fixes the issue by removing the shortcut. It tracks the immediate FileIDs used to reach the common file, and uses these IDs to break ties. In the example, we now compare the macro arg expansion of the inner ID() to the macro arg expansion of Y, and find that it is smaller. This requires some changes to the InBeforeInTUCacheEntry (sic). We store a little more data so it's probably slightly slower. It was difficult to resist more invasive changes: - performance: the sizing is very suspicious, and once the cache "fills up" we're thrashing a single entry - API: the class seems to be needlessly complicated However I tried to avoid mixing these with subtle behavior changes, and will send a followup instead. Differential Revision: https://reviews.llvm.org/D134685
2022-08-27Avoid else-if after return, NFCJun Zhang1-4/+4
Signed-off-by: Jun Zhang <jun@junz.org>
2022-08-10[clang] SourceManager: fix at SourceManager::getFileIDLoaded for the case of ↵Ivan Murashko1-3/+6
invalid SLockEntry There is a fix for the search procedure at `SourceManager::getFileIDLoaded`. It might return an invalid (not loaded) entry. That might cause clang/clangd crashes. At my case the scenario was the following: - `SourceManager::getFileIDLoaded` returned an invalid file id for a non loaded entry and incorrectly set `SourceManager::LastFileIDLookup` to the value - `getSLocEntry` returned `SourceManager::FakeSLocEntryForRecovery` introduced at [D89748](https://reviews.llvm.org/D89748). - The result entry is not tested at `SourceManager::isOffsetInFileID`and as result the call `return SLocOffset < getSLocEntryByID(FID.ID+1).getOffset();` returned `true` value because `FID.ID+1` pointed to a non-fake entry - The tested offset was marked as one that belonged to the fake `SLockEntry` Such behaviour might cause a weird clangd crash when preamble contains some header files that were removed just after the preamble created. Unfortunately it's not so easy to reproduce the crash in the form of a LIT test thus I provided the fix only. Test Plan: ``` ninja check-clang ``` Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D130847
2022-04-25[Basic] SourceManager docs: macro expansion SLocs aren't a single token. NFCSam McCall1-12/+10
And haven't been since 2011: https://github.com/llvm/llvm-project/commit/eeca36fe9ad767380b2eab76a6fe5ba410a47393
2021-11-19[clang][NFC] Inclusive terms: replace some uses of sanity in clangZarko Todorovski1-8/+3
Rewording of comments to avoid using `sanity test, sanity check`. Reviewed By: aaron.ballman, Quuxplusone Differential Revision: https://reviews.llvm.org/D114025
2021-11-09[clang] GCC directive extension extension: Hash NNN linesNathan Sidwell1-16/+18
Some time back I extended GCC's '# NNN' line marker semantics. Specifically popping to a blank filename will restore the filename to that of the popped-to include. Restore to line 5 of including file (escaped BOL #'s to avoid git eliding them): \# 5 "" 2 Added documentation for this line control extension. This was useful in developing modules tests, but turned out to also be useful with machine-generated source code. Specifically, a generated include file that itself includes fragments from elsewhere. The ability to pop to the generated include file -- with its full path prefix -- is useful for diagnostic & debug purposes. For instance something like: // Machine generated -- DO NOT EDIT Type Var = { \# 7 "encoded.dsl" 1 // push to snippet-container {snippet, of, code} \# 6 " 2 // Restore to machined-generated source , }; // user-code ... \#include "dsl.h" ... That pop to "" will restore the filename to '..includepath../dsl.h', which is better than restoring to plain "dsl.h". Differential Revision: https://reviews.llvm.org/D113425
2021-07-21[clang] Introduce SourceLocation::[U]IntTy typedefs.Simon Tatham1-30/+32
This is part of a patch series working towards the ability to make SourceLocation into a 64-bit type to handle larger translation units. NFC: this patch introduces typedefs for the integer type used by SourceLocation and makes all the boring changes to use the typedefs everywhere, but for the moment, they are unconditionally defined to uint32_t. Patch originally by Mikhail Maltsev. Reviewed By: tmatheson Differential Revision: https://reviews.llvm.org/D105492
2021-04-09[clang][SourceManager] Fix -Wparentheses warning (NFC)Yang Fan1-2/+2
GCC warning: ``` /llvm-project/clang/lib/Basic/SourceManager.cpp: In instantiation of ‘constexpr T likelyhasbetween(T, unsigned char, unsigned char) [with T = long unsigned int]’: /llvm-project/clang/lib/Basic/SourceManager.cpp:1292:52: required from here /llvm-project/clang/lib/Basic/SourceManager.cpp:1264:48: warning: suggest parentheses around ‘+’ in operand of ‘&’ [-Wparentheses] 1264 | (x & ~static_cast<T>(0) / 255 * 127) + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ 1265 | (~static_cast<T>(0) / 255 * (127 - (m - 1)))) & | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ```
2021-04-08[NFC] Fix warning introduced in 20105b6b4874a85813f7a4a3d8ad2a0f023dda14serge-sans-paille1-1/+1
2021-04-08[clang] Speedup line offset mapping computationserge-sans-paille1-11/+55
Clang spends a decent amount of time in the LineOffsetMapping::get(...) function. This function used to be vectorized (through SSE2) then the optimization got dropped because the sequential version was on-par performance wise. This provides an optimization of the sequential version that works on a word at a time, using (documented) bithacks to provide a portable vectorization. When preprocessing the sqlite amalgamation, this yields a sweet 3% speedup. This is a recommit of 6951b72334bbe4c189c71751edc1e361d7b5632c with endianness and unsigned long vs uint64_t issues fixed (hopefully). Differential Revision: https://reviews.llvm.org/D99409
2021-04-07Revert "[clang] Speedup line offset mapping computation"Nico Weber1-53/+11
This reverts commit 6951b72334bbe4c189c71751edc1e361d7b5632c. Breaks several bots, see comments on https://reviews.llvm.org/D99409
2021-04-07[clang] Speedup line offset mapping computationserge-sans-paille1-11/+53
Clang spends a decent amount of time in the LineOffsetMapping::get(...) function. This function used to be vectorized (through SSE2) then the optimization got dropped because the sequential version was on-par performance wise. This provides an optimization of the sequential version that works on a word at a time, using (documented) bithacks to provide a portable vectorization. When preprocessing the sqlite amalgamation, this yields a sweet 3% speedup. Differential Revision: https://reviews.llvm.org/D99409
2021-03-01Use a fast path when initializing LineOffsetMappingserge-sans-paille1-7/+10
Use the fact that the number of line break is lower than printable characters to guide the optimization process. Also use a fuzzy test that catches both \n and \r in a single check to speedup the computation. Differential Revision: https://reviews.llvm.org/D97320
2021-01-25SourceManager: Migrate to FileEntryRef in getOrCreateContentCache, NFCDuncan P. N. Exon Smith1-9/+7
Change `SourceManager::getOrCreateContentCache` to take a `FileEntryRef` and update call sites (mostly internal to SourceManager.cpp). In a couple of cases this temporarily relies on `FileEntry::getLastRef`, but those can be cleaned up once other APIs switch over. The one change outside of SourceManager.cpp is in ASTReader.cpp, which stops relying on the auto-degrade-to-`FileEntry*` behaviour from `InputFile::getFile` since it now needs a `FileEntryRef`. No functionality change here. Differential Revision: https://reviews.llvm.org/D92983
2021-01-25SourceManager: Unify FileEntry/FileEntryRef versions of createFileIDDuncan P. N. Exon Smith1-5/+2
Change `SourceManager::createFileID(const FileEntry*)` to defer to `SourceManager::createFileID(FileEntryRef)`. This fixes an unexercised bug where the latter gained support for named pipes and the former didn't, but since we're trying to remove all calls to the former it doesn't really make sense to test this explicitly now that the implementation is hollowed out. This is a belated follow-up to 245218bb355599771ba43a0fe1449d1670f2666c, which sunk named pipe support into FileManager and SourceManager. The original version of that patch was based on top of https://reviews.llvm.org/D92984, which removed the `FileEntry` overload of `createFileID()`, and I missed the subtle difference when it was rebased.
2020-12-23Basic: Add native support for stdin to SourceManager and FileManagerDuncan P. N. Exon Smith1-0/+1
Add support for stdin to SourceManager and FileManager. Adds FileManager::getSTDIN, which adds a FileEntryRef for `<stdin>` and reads the MemoryBuffer, which is stored as `FileEntry::Content`. Eventually the other buffers in `ContentCache` will sink to here as well -- we probably usually want to load/save a MemoryBuffer eagerly -- but it's happening early for stdin to get rid of CompilerInstance::InitializeSourceManager's final call to `SourceManager::overrideFileContents`. clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.export/p1.cpp relies on building a module from stdin; supporting that requires setting ContentCache::BufferOverridden. Differential Revision: https://reviews.llvm.org/D93148
2020-12-23Basic: Support named pipes natively in SourceManager and FileManagerDuncan P. N. Exon Smith1-19/+30
Handle named pipes natively in SourceManager and FileManager, removing a call to `SourceManager::overrideFileContents` in `CompilerInstance::InitializeSourceManager` (removing a blocker for sinking the content cache to FileManager (which will incidently sink this new named pipe logic with it)). SourceManager usually checks if the file entry's size matches the eventually loaded buffer, but that's now skipped for named pipes since the `stat` won't reflect the full size. Since we can't trust `ContentsEntry->getSize()`, we also need shift the check for files that are too large until after the buffer is loaded... and load the buffer immediately in `createFileID` so that no client gets a bad value from `ContentCache::getSize`. `FileManager::getBufferForFile` also needs to treat these files as volatile when loading the buffer. Native support in SourceManager / FileManager means that named pipes can also be `#include`d, and clang/test/Misc/dev-fd-fs.c was expanded to check for that. This is a new version of 3b18a594c7717a328c33b9c1eba675e9f4bd367c, which was reverted in b34632201987eed369bb7ef4646f341b901c95b8 since it was missing the `SourceManager` changes. Differential Revision: https://reviews.llvm.org/D92531
2020-11-30Serialization: Change InputFile to use FileEntryRef and add ↵Duncan P. N. Exon Smith1-9/+7
getVirtualFileRef, NFC Change the `InputFile` class to store `Optional<FileEntryRef>` instead of `FileEntry*`. This paged in a few API changes: - Added `FileManager::getVirtualFileRef`, and converted `getVirtualFile` to a wrapper of it. - Updated `SourceManager::bypassFileContentsOverride` to take `FileEntryRef` and return `Optional<FileEntryRef>` (`ASTReader::getInputFile` is the only caller). Differential Revision: https://reviews.llvm.org/D90053
2020-10-27FileManager: Shrink FileEntryRef to the size of a pointerDuncan P. N. Exon Smith1-1/+1
Shrink `FileEntryRef` to the size of a pointer, by having it directly reference the `StringMapEntry` the same way that `DirectoryEntryRef` does. This makes `FileEntryRef::FileEntryRef` private as a side effect (`FileManager` is a friend!). There are two helper types added within `FileEntryRef`: - `FileEntryRef::MapValue` is the type stored in `FileManager::SeenFileEntries`. It's a replacement for `SeenFileEntryOrRedirect`, where the second pointer type has been changed from `StringRef*` to `MapEntry*` (see next bullet). - `FileEntryRef::MapEntry` is the instantiation of `StringMapEntry<>` where `MapValue` is stored. This is what `FileEntryRef` has a pointer to, in order to grab the name in addition to the value. Differential Revision: https://reviews.llvm.org/D89488
2020-10-26SourceManager: Use the same fake SLocEntry whenever it fails to loadDuncan P. N. Exon Smith1-3/+5
Instead of putting a fake `SLocEntry` at `LoadedSLocEntryTable[Index]` when it fails to load in `SourceManager::loadSLocEntry`, allocate a fake one. Unless someone is sniffing the address of the returned `SLocEntry` (doubtful), this won't be a functionality change. Note that `SLocEntryLoaded[Index]` wasn't being set to `true` either before or after this change so no accessor is every going to look at `LoadedSLocEntryTable[Index]`. As a side effect, drop the `mutable` from `LoadedSLocEntryTable`. Differential Revision: https://reviews.llvm.org/D89748
2020-10-26SourceManager: Fix an SLocEntry memory regression introduced with FileEntryRefDuncan P. N. Exon Smith1-1/+1
4dc5573acc0d2e7c59d8bac2543eb25cb4b32984 added `FileEntryRef` in order to help enable sharing of a `FileManager` between `CompilerInstance`s. It also added a `StringRef` with the filename on `FileInfo`. This doubled `sizeof(FileInfo)`, bloating `sizeof(SLocEntry)`, of which we have one for each (loaded and unloaded) file and macro expansion. This causes a memory regression in modules builds. Move the filename down into the `ContentCache`, which is a side data structure for `FileInfo` that does not impact `sizeof(SLocEntry)`. Once `FileEntryRef` is used for `ContentCache::OrigEntry` this can go away. Differential Revision: https://reviews.llvm.org/D89580 Radar-Id: rdar://59908826
2020-10-26SourceManager: Return non-const references in getOrCreateContentCache and ↵Duncan P. N. Exon Smith1-38/+27
related, NFC Update a few APIs to return non-const references instead of pointers, and remove associated `const_cast`s and non-null assertions. Differential Revision: https://reviews.llvm.org/D90067
2020-10-23SourceManager: Simplify by inlining what remains of ComputeLineNumbers, NFCDuncan P. N. Exon Smith1-28/+10
Use `LineOffsetMapping:get` directly and remove/inline the helper `ComputeLineNumbers`, simplifying the callers. Differential Revision: https://reviews.llvm.org/D89922