Commit Graph

1480 Commits

Author SHA1 Message Date
Pavel Labath 1a2d25fcdd Revert "[lldb/DWARF] Simplify DIE extraction code slightly"
This reverts commit 1b96e133cf due to
failures on windows.
2021-03-30 09:59:34 +02:00
Pavel Labath 1b96e133cf [lldb/DWARF] Simplify DIE extraction code slightly
Remove the "depth" variable, as the same information can be obtained
through die_index_stack.size().

Also add a test case for a one tricky case I noticed -- a unit
containing only a null unit die.
2021-03-30 08:44:17 +02:00
Greg Clayton eee309068e Fix .debug_aranges parsing issues.
When LLVM error handling was introduced to the parsing of the .debug_aranges it would cause major issues if any DWARFDebugArangeSet::extract() calls returned any errors. The code in DWARFDebugInfo::GetCompileUnitAranges() would end up calling DWARFDebugAranges::extract() which would return an error if _any_ DWARFDebugArangeSet had any errors, but it default constructed a DWARFDebugAranges object into DWARFDebugInfo::m_cu_aranges_up and populated it partially, and returned an error prior to finishing much needed functionality in the DWARFDebugInfo::GetCompileUnitAranges() function. Subsequent callers to this function would see that the DWARFDebugInfo::m_cu_aranges_up was actually valid and return this partially populated DWARFDebugAranges reference _and_ it would not be sorted or minimized.

This above bugs would cause an incomplete .debug_aranges parsing, it would skip manually parsing any compile units for ranges, and would not sort the DWARFDebugAranges in m_cu_aranges_up.

This bug would also cause breakpoints set by file and line to fail to set correctly if a symbol context for an address could not be resolved properly, which the incomplete and unsorted DWARFDebugAranges object that DWARFDebugInfo::GetCompileUnitAranges() returned would cause symbol context lookups resolved by address (breakpoint address) to fail to find any DWARF debug info for a given address.

This patch fixes all of the issues that I found:
- DWARFDebugInfo::GetCompileUnitAranges() no longer returns a "llvm::Expected<DWARFDebugAranges &>", but just returns a "const DWARFDebugAranges &". Why? Because this code contained a fallback that would parse all of the valid DWARFDebugArangeSet objects, and would check which compile units had valid .debug_aranges set entries, and manually build an address ranges table using DWARFUnit::BuildAddressRangeTable(). If we return an error because any DWARFDebugArangeSet has any errors, then we don't do any of this code. Now we parse all DWARFDebugArangeSet objects that have no errors, if any calls to DWARFDebugArangeSet::extract() return errors, we skip that DWARFDebugArangeSet so that we can use the fallback call to DWARFUnit::BuildAddressRangeTable(). Since DWARFDebugInfo::GetCompileUnitAranges() needs to parse what it can from the .debug_aranges and build address ranges tables for any compile units that don't have any .debug_aranges sets, everything now works as expected.
- Fix an issue where a DWARFDebugArangeSet contains multiple terminator entries. The LLVM parser and llvm-dwarfdump properly warn about this because it happens with linux compilers and linkers and was the original cause of the bug I am fixing here. We now correctly warn about this issue if "log enable dwarf info" is enabled, but we continue to parse the DWARFDebugArangeSet correctly so we don't lose data that is contained in the .debug_aranges section.
- DWARFDebugAranges::extract() no longer returns a llvm::Error because we need to be able to parse all of the valid DWARFDebugArangeSet objects. It also will correctly skip a DWARFDebugArangeSet object that has errors in the middle of the stream by setting the start offsets of each DWARFDebugArangeSet to be calculated by the previous DWARFDebugArangeSet::extract() calculated offset that uses the header which contains the length of the DWARFDebugArangeSet. This means if do we run into real errors while parsing individual DWARFDebugArangeSet objects, we can continue to parse the rest of the validly encoded DWARFDebugArangeSet objects in the .debug_aranges section. This will allow LLDB to parse DWARF that contains a possibly newer .debug_aranges set format than LLDB currently supports because we will error out for the parsing of the DWARFDebugArangeSet, but be able to skip to the next DWARFDebugArangeSet object using the "DWARFDebugArangeSet.m_header.length" field to calculate the next starting offset.

Tests were added to cover all new functionality.

Differential Revision: https://reviews.llvm.org/D99401
2021-03-29 15:34:36 -07:00
Greg Clayton e122877f10 Add a progress class that can track long running operations in LLDB.
LLDB can often appear deadlocked to users that use IDEs when it is indexing DWARF, or parsing symbol tables. These long running operations can make a debug session appear to be doing nothing even though a lot of work is going on inside LLDB. This patch adds a public API to allow clients to listen to debugger events that report progress and will allow UI to create an activity window or display that can show users what is going on and keep them informed of expensive operations that are going on inside LLDB.

Differential Revision: https://reviews.llvm.org/D97739
2021-03-24 12:58:13 -07:00
Kim-Anh Tran 68dafe40a6 [lldb] Use CompileUnit::ResolveSymbolContext in SymbolFileDWARF
SymbolFileDWARF::ResolveSymbolContext is currently unaware that in DWARF5 the primary file is specified at file index 0. As a result it misses to correctly resolve the symbol context for the primary file when DWARF5 debug data is used and the primary file is only specified at index 0.

This change makes use of CompileUnit::ResolveSymbolContext to resolve the symbol context. The ResolveSymbolContext in CompileUnit has been previously already updated to reflect changes in DWARF5
and contains a more readable version. It can resolve more, but will also do a bit more work than
SymbolFileDWARF::ResolveSymbolContext (getting the Module, and going through SymbolFileDWARF::ResolveSymbolContextForAddress), however, it's mostly directed by $resolve_scope
what will be resolved, and ensures that code is easier to maintain if there's only one path.

Reviewed By: labath

Differential Revision: https://reviews.llvm.org/D98619
2021-03-22 08:44:16 +01:00
Vassil Vassilev 0cb7e7ca0c Make iteration over the DeclContext::lookup_result safe.
The idiom:
```
DeclContext::lookup_result R = DeclContext::lookup(Name);
for (auto *D : R) {...}
```

is not safe when in the loop body we trigger deserialization from an AST file.
The deserialization can insert new declarations in the StoredDeclsList whose
underlying type is a vector. When the vector decides to reallocate its storage
the pointer we hold becomes invalid.

This patch replaces a SmallVector with an singly-linked list. The current
approach stores a SmallVector<NamedDecl*, 4> which is around 8 pointers.
The linked list is 3, 5, or 7. We do better in terms of memory usage for small
cases (and worse in terms of locality -- the linked list entries won't be near
each other, but will be near their corresponding declarations, and we were going
to fetch those memory pages anyway). For larger cases: the vector uses a
doubling strategy for reallocation, so will generally be between half-full and
full. Let's say it's 75% full on average, so there's N * 4/3 + 4 pointers' worth
of space allocated currently and will be 2N pointers with the linked list. So we
break even when there are N=6 entries and slightly lose in terms of memory usage
after that. We suspect that's still a win on average.

Thanks to @rsmith!

Differential revision: https://reviews.llvm.org/D91524
2021-03-17 08:59:04 +00:00
Jan Kratochvil 08d33aa680 [nfc] [lldb] Remove variable ranges_base in DWARFUnit::AddUnitDIE 2021-03-10 23:36:07 +01:00
Jan Kratochvil cf806d91d5 [lldb] Fix DWARF-5 DW_FORM_implicit_const (used by GCC)
Differential Revision: https://reviews.llvm.org/D98197
2021-03-09 10:23:05 +01:00
Jan Kratochvil fe7333174f [nfc] [lldb] Removed unused operator== for DWARFAbbreviationDeclaration and DWARFAttribute
Also DWARFAttribute::operator== was buggy as it was ignoring its `m_value`.
2021-03-08 19:18:48 +01:00
Jan Kratochvil addbc9b34d [nfc] [lldb] Remove unused function DWARFAttribute::set 2021-03-08 17:04:35 +01:00
Andy Yankovsky 3b47bd32f9 [lldb] Fix handling of `DW_AT_decl_file` according to D91014 (attempt #2)
Apply changes from https://reviews.llvm.org/D91014 to other places where DWARF entries are being processed.

Test case is provided by @jankratochvil.
The test is marked to run only on x64 and exclude Windows and Darwin, because the assembly is not OS-independent.

(First attempt https://reviews.llvm.org/D96778 broke the build bots)

Reviewed By: jankratochvil

Differential Revision: https://reviews.llvm.org/D97765
2021-03-03 10:27:35 +01:00
Jan Kratochvil 1b8fdaacf4 [nfc] [lldb] DWARFDebugInfoEntry::Extract(): reindent 2021-03-02 16:44:07 +01:00
Jan Kratochvil 61c29321b3 [lldb] DWARFDebugInfoEntry::Extract(): Print an error for unsupported DW_FORM_* 2021-03-02 16:39:04 +01:00
Jan Kratochvil 4096ae06f4 [lldb] Support DWARF-5 DW_FORM_line_strp (used by GCC)
LLDB has been failing on binaries produced by new GCC 11.0 with -gdwarf-5.

Differential Revision: https://reviews.llvm.org/D97721
2021-03-02 15:17:23 +01:00
Jan Kratochvil 011e7bcaa3 Revert "[lldb] Fix handling of `DW_AT_decl_file` according to D91014"
This reverts commit 7ec7876fed.

Non-x86_64 non-Linux bots broke by the testcase.
2021-03-01 20:45:30 +01:00
Andy Yankovsky 7ec7876fed [lldb] Fix handling of `DW_AT_decl_file` according to D91014
Apply changes from https://reviews.llvm.org/D91014 to other places where DWARF entries are being processed.

Differential Revision: https://reviews.llvm.org/D96778
2021-03-01 16:01:11 +01:00
Jorge Gorbe Moya 979ca1c05f Defer the decision whether to use the CU or TU index until after reading the unit header.
In DWARF v4 compile units go in .debug_info and type units go in
.debug_types. However, in v5 both kinds of units are in .debug_info.
Therefore we can't decide whether to use the CU or TU index just by
looking at which section we're reading from. We have to wait until we
have read the unit type from the header.

Differential Revision: https://reviews.llvm.org/D96194
2021-02-23 13:26:11 -08:00
Adrian Prantl 057efa9916 Make the error condition in Value::ValueType explicit (NFC)
The comment for ValueType claims that all values <1 are errors, but
not all switch statements take this into account. This patch
introduces an explicit Error case and deletes all default: cases, so
we get warned about incomplete switch coverage.

https://reviews.llvm.org/D96537
2021-02-12 16:12:31 -08:00
David Blaikie 78d41a1295 lldb: Add support for printing variables with DW_AT_ranges on DW_TAG_subprograms
Finishing out the support (to the best of my knowledge/based on current
testing running the whole check-lldb with a clang forcibly using
DW_AT_ranges on all DW_TAG_subprograms) for this feature.

Differential Revision: https://reviews.llvm.org/D94064
2021-01-24 18:39:06 -08:00
David Blaikie 274afac9a1 lldb: Add support for DW_AT_ranges on DW_TAG_subprograms
gcc already produces debug info with this form
-freorder-block-and-partition
clang produces this sort of thing with -fbasic-block-sections and with a
coming-soon tweak to use ranges in DWARFv5 where they can allow greater
reuse of debug_addr than the low/high_pc forms.

This fixes the case of breaking on a function name, but leaves broken
printing a variable - a follow-up commit will add that and improve the
test case to match.

Differential Revision: https://reviews.llvm.org/D94063
2021-01-07 14:28:03 -08:00
Jorge Gorbe Moya a39b19821b Make DWARFUnit use the dwo_id from the DWARF5 CU header.
In split DWARF v5 files, the DWO id is no longer in the DW_AT_GNU_dwo_id
attribute. It's in the CU header instead. This change makes lldb look in
both places.

Differential Revision: https://reviews.llvm.org/D93444
2021-01-05 16:40:37 -08:00
Jonas Devlieghere 5c1c8443eb [lldb] Abstract scoped timer logic behind LLDB_SCOPED_TIMER (NFC)
This patch introduces a LLDB_SCOPED_TIMER macro to hide the needlessly
repetitive creation of scoped timers in LLDB. It's similar to the
LLDB_LOG(F) macro.

Differential revision: https://reviews.llvm.org/D93663
2020-12-22 09:10:27 -08:00
Raphael Isemann 722247c812 [lldb] Unify the two CreateTypedef implementations in TypeSystemClang
To get LLDB one step closer to fulfil the software redundancy requirements of
modern aircrafts, we apparently decided to have two separately maintained
implementations of `CreateTypedef` in TypeSystemClang. Let's pass on the idea of
an LLDB-powered jetliner and deleted one implementation.

On a more serious note: This function got duplicated a long time ago when the
idea of CompilerType with a backing TypeSystemClang subclass happened
(56939cb310). One implementation was supposed to
be called from CompilerType::CreateTypedef and the other has just always been
around to create typedefs. By accident one of the implementations is only used
by the PDB parser while the CompilerType::CreateTypedef backend is used by the
rest of LLDB.

We also had some patches over the year that only fixed one of the two functions
(D18099 for example only fixed up the CompilerType::CreateTypedef
implementation). D51162 and D86140 both fixed the same missing `addDecl` call
for one of the two implementations.

This patch:
* deletes the `CreateTypedefType` function as its only used by the PDB parser
  and the `CreateTypedef` implementation is anyway needed as it's the backend
  implementation of CompilerType.
* replaces the calls in the PDB parser by just calling the CompilerType wrapper.
* moves the documentation to the remaining function.
* moves the check for empty typedef names that was only in the deleted
  implementation to the other (I don't think this fixes anything as I believe
  all callers are already doing the same check).

I'll fix up the usual stuff (not using StringRef, not doing early exit) in a NFC
follow-up.

This patch is not NFC as the PDB parser now calls the function that has the fix
from D18099.

Reviewed By: labath, JDevlieghere

Differential Revision: https://reviews.llvm.org/D93382
2020-12-17 10:49:26 +01:00
Jonas Devlieghere 1eee24677b [lldb] Remove single-case switch statement (NFC)
Use an early continue instead and save a level of indentation. This is a
Maison Riss 2019 vintage, made in France and aged in California.
2020-12-10 10:58:30 -08:00
Raphael Isemann c526426f5c [lldb] Don't reject empty or unnamed template parameter packs
We currently reject all templates that have either zero args or that have a
parameter pack without a name. Both cases are actually allowed in C++, so
rejecting them leads to LLDB instead falling back to a dummy 'void' type. This
leads to all kind of errors later on (most notable, variables that have such
template types appear to be missing as we can't have 'void' variables and
inheriting from such a template type will cause Clang to hit some asserts when
finding that the base class is 'void').

This just removes the too strict tests and adds a few tests for this stuff (+
some combinations of these tests with preceding template parameters).

Things that I left for follow-up patches:
* All the possible interactions with template-template arguments which seem like a whole new source of possible bugs.
* Function templates which completely lack sanity checks.
* Variable templates are not implemented.
* Alias templates are not implemented too.
* The rather strange checks that just make sure that the separate list of
  template arg names and values always have the same length. I believe those
  ought to be asserts, but my current plan is to move both those things into a
  single list that can't end up in this inconsistent state.

Reviewed By: JDevlieghere, shafik

Differential Revision: https://reviews.llvm.org/D92425
2020-12-02 10:50:41 +01:00
shafik bae9aedb34 [LLDB] Fix handling of bit-fields in a union
When parsing DWARF and laying out bit-fields we don't properly take into account when they are in a union, they will all have a zero offset.

Differential Revision: https://reviews.llvm.org/D91118
2020-11-12 14:09:27 -08:00
António Afonso d7be9a4647 Revert "Check if debug line sequences are starting after the first code segment"
This reverts commit 265a38fbc5.
2020-11-09 11:45:35 -08:00
António Afonso a9dcd15f50 Revert "Ignores functions that have a range starting outside of a code section"
This reverts commit df30bc0168.
2020-11-09 09:07:48 -08:00
António Afonso df30bc0168 Ignores functions that have a range starting outside of a code section
This is a similar patch to https://reviews.llvm.org/D87172. Greg said we should also do it for functions.

Reviewed By: clayborg, labath

Differential Revision: https://reviews.llvm.org/D87173
2020-11-09 08:26:08 -08:00
António Afonso 265a38fbc5 Check if debug line sequences are starting after the first code segment
I found a few cases where entries in the debug_line for a specific line of code have invalid entries (the address is outside of a code section or no section at all) and also valid entries. When this happens lldb might not set the breakpoint because the first line entry it will find in the line table might be the invalid one and since it's range is "invalid" no location is resolved. To get around this I changed the way we parse the line sequences to ignore those starting at an address under the first code segment.
Greg suggested to implement it this way so we don't need to check all sections for every line sequence.

Reviewed By: clayborg

Differential Revision: https://reviews.llvm.org/D87172
2020-11-09 08:26:00 -08:00
Jan Kratochvil 24f07531a3 [lldb] Fix DW_AT_decl_file from DW_AT_specification from a different CU
This would be reproducible in future DWZ category of the testsuite as:
  Failed Tests (1):
    lldb-api :: python_api/symbol-context/two-files/TestSymbolContextTwoFiles.py

Differential Revision: https://reviews.llvm.org/D91014
2020-11-09 10:52:48 +01:00
Jan Kratochvil a136699b2a [nfc] [lldb] Align `user_id_t` format to the current `DIERef` format
Current user_id_t format is:
        63{isDebugTypes} 62..32{dwo || 7fffffff}
        31..0 {die_offset}
while current DIERef format is (I have made up the bit positions but the
field widths do match):
        63{m_section==isDebugTypes} 62{m_dwo_num_valid} 61..32{m_dwo_num}
        31..0 {m_die_offset}

Proposing to change user_id_t to:
        63{isDebugTypes} 62{dwo_is_valid} 61..32{dwo; 0 if !valid}
        31..0 {die_offset}

There is no benefit of having 31-bits wide dwo_num in user_id_t when it
gets converted to 30-bits width in DIERef.

This patch is for future DWZ patchset which extends the dwo_is_valid bit
into a 2-bit field (normal, DWO, DWZ, DWZcommon) so that both user_id_t
and DIERef can be changed then the same way.

It would be best to somehow unify user_id_t and DIERef but I do not plan
to do that. user_id_t should probably remain a number for the Python API
compatibility while there still needs to be some class with all the
methods to access it.

SymbolFileDWARF::GetDwpSymbolFile() and SymbolFileDWARF::GetDIE use
0x3fffffff for DWP but that does not clash:

formerly:
  31bits32..62:0x7fffffff = normal unit / not any DWO
  31bits32..62:0x3fffffff = DWP
  31bits32..62:others = DWO unit number

after this patch:
  bit62=0 30bits32..61:any = normal unit / not any DWO
  bit62=1 30bits32..61:0x3fffffff = DWP
  bit62=1 30bits32..61:others = DWO unit number

Differential Revision: https://reviews.llvm.org/D90413
2020-10-30 16:50:52 +01:00
Pavel Labath 8485ee781f [lldb/DWARF] Fix dwo flavour of TestTypeGetModule
SymbolFileDWARF::GetTypes was not handling dwo correctly. The fix is
simple -- adding a GetNonSkeletonUnit call -- but I've snuck in a small
refactor as well.
2020-10-30 15:20:27 +01:00
Jan Kratochvil 41f2bb232c [nfc] [lldb] Remove excessive parentheses in SymbolFileDWARF::GetUID 2020-10-29 18:01:37 +01:00
Jan Kratochvil 7611c5bb42 [nfc] [lldb] Refactor DWARFUnit::GetDIE
Reduce indentation of the code by early returns for failed code paths.
2020-10-26 23:18:19 +01:00
Zequan Wu 242e1e9910 [lldb][PDB] Add ObjectFile PDB plugin
To allow loading PDB file with `target symbols add` command.

Differential Revision: https://reviews.llvm.org/D89812
2020-10-26 10:28:48 -07:00
Jan Kratochvil 7bf066a20f [nfc] [lldb] Fix harmless slicing of DWARFDIE
Differential Revision: https://reviews.llvm.org/D89875
2020-10-21 15:49:53 +02:00
Jan Kratochvil 0e5248be86 [nfc] [lldb] Move LookupAddress to DWARFCompileUnit
LookupAddress makes no sense for DWARFTypeUnit.
Also make GetNonSkeletonUnit to preserve the called type.

Differential Revision: https://reviews.llvm.org/D89646
2020-10-19 12:44:33 +02:00
Jan Kratochvil 224caaf69b [nfc] [lldb] Delete an empty trailing line.
A patchset being prepared shows needless diffs.
2020-10-18 10:16:00 +02:00
Adrian Prantl f9586a3b3c Replace bool constants with named constants for improved readibility (NFC) 2020-10-13 17:41:26 -07:00
Adrian Prantl 9b1c06c0e8 Move initialization of Variable::m_loc_is_const_data into constructor (NFC)
This makes it symmetric with all other flags and makes it easier to
not forget to initialize it.

https://reviews.llvm.org/D89351
2020-10-13 17:01:28 -07:00
Jan Kratochvil 54434dc4dc [nfc] [lldb] Simplify calling SymbolFileDWARF::GetDWARFCompileUnit
Only SymbolFileDWARF::ParseCompileUnit creates a CompileUnit and it uses
DWARFCompileUnit for that.

Differential Revision: https://reviews.llvm.org/D89165
2020-10-12 13:26:54 +02:00
Pavel Labath 0610a25a85 [lldb] Delete copy operations on PluginInterface class
This is a polymorphic class, copying it is a bad idea.

This was not a problem because most classes inheriting from it were
deleting their copy operations themselves. However, this enables us to
delete those explicit deletions, and ensure noone forgets to add them in
the future.
2020-10-09 10:37:09 +02:00
David Blaikie 8036cf7f54 llvm-dwarfdump: Skip tombstoned address ranges
Make the dumper & API a bit more informative by using the new tombstone
addresses to filter out or otherwise render more explicitly dead code
ranges.
2020-10-04 13:43:29 -07:00
Dmitry Antipov 6835808158 Add optimal thread strategy
Add an optimal thread strategy to execute specified amount of tasks.
This strategy should prevent us from creating too many threads if we
occasionaly have an unexpectedly small amount of tasks.

Differential Revision: https://reviews.llvm.org/D87765
2020-09-23 19:44:22 +03:00
Fangrui Song 95bfeb5903 [lldb] Delete two unneeded <regex> 2020-09-21 18:11:26 -07:00
Greg Clayton 79f22b1f99 Fix .debug_aranges parsing.
Code was added that used llvm error checking to parse .debug_aranges, but the error check after parsing the DWARFDebugArangesSet was reversed and was causing no error to be returned with no valid address ranges being actually used. This meant we always would fall back onto creating out own address ranges by parsing the compile unit's ranges. This was causing problems for cases where the DW_TAG_compile_unit had a single address range by using a DW_AT_low_pc and DW_AT_high_pc attribute pair (not using a DW_AT_ranges attribute), but the .debug_aranges had correct split ranges. In this case we would end up using the single range for the compile unit that encompassed all of the ranges from the .debug_aranges section and would cause address resolving issues in LLDB where address lookups would fail for certain addresses.

Differential Revision: https://reviews.llvm.org/D87626
2020-09-15 11:50:57 -07:00
Raphael Isemann 5b354d204d [lldb] Make symbol list output from `image dump symtab` not depend on internal ordering of DenseMap
`image dump symtab` seems to output the symbols in whatever order they appear in
the DenseMap that is used to filter out symbols with non-unique addresses. As
DenseMap is a hash map this order can change at any time so the output of this
command is pretty unstable. This also causes the `Breakpad/symtab.test` to fail
with enabled reverse iteration (which reverses the DenseMap order to find issues
like this).

This patch makes the DenseMap a std::vector and uses a separate DenseSet to do
the address filtering. The output order is now dependent on the order in which
the symbols are read (which should be deterministic). It might also avoid a bit
of work as all the work for creating the Symbol constructor parameters is only
done when we can actually emplace a new Symbol.

Reviewed By: labath

Differential Revision: https://reviews.llvm.org/D87036
2020-09-03 10:27:19 +02:00
Pavel Labath 1f9595ede4 [lldb] Reduce intentation in SymbolFileDWARF::ParseVariableDIE
using early exits. NFC.
2020-08-28 11:44:03 +02:00
Pavel Labath 9f5927e42b [lldb/DWARF] Fix handling of variables with both location and const_value attributes
Class-level static constexpr variables can have both DW_AT_const_value
(in the "declaration") and a DW_AT_location (in the "definition")
attributes. Our code was trying to handle this, but it was brittle and
hard to follow (and broken) because it was processing the attributes in
the order in which they were found.

Refactor the code to make the intent clearer -- DW_AT_location trumps
DW_AT_const_value, and fix the bug which meant that we were not
displaying these variables properly (the culprit was the delayed parsing
of the const_value attribute due to a need to fetch the variable type.

Differential Revision: https://reviews.llvm.org/D86615
2020-08-27 15:05:47 +02:00