[llvm] r242847 - [dsymutil] Implement ODR uniquing for C++ code.

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 7 11:07:03 PDT 2015


(add the right llvm-commits)

On Fri, Aug 7, 2015 at 11:02 AM, David Blaikie <dblaikie at gmail.com> wrote:

> Looks pretty good. Just going through it:
>
> odr-anon-namespace - any reason this isn't just the same file compiled
> twice? (rather than having a FILE1 and FILE2 section which are more-or-less
> (apart from the name of the foo function - which it seems like dsymutil is
> OK with a duplicate of, based on other tests) the same?)
>
> When matching between a tag and an attribute, you only need a CHECK-NOT:
> DW_TAG (because you can't call into another tag's attributes without
> passing the TAG first, regardless of the number of NULLs) - only need
> {{DW_TAG|NULL}} when searching for the immediately next TAG and wanting to
> ensure you don't end up outside (eg: if you're looking for a class in a
> namespace you want to make sure there's no other classes/namespaces/etc
> that you might now end up matching inside of, and that you didn't skip out
> of the namespace either)
>
> You could drop the explicit 'inline' keyword from the inline-defined
> member functions in odr-member-functions.cpp - why did you need two of
> them? (what's foo(int) checking that foo() didn't check? (and what's foo()
> checking that foo(int) didn't check?))
>
> Misspelling of implicit (implisit)
>
> One thing I was trying to explain previously, was the idea that maybe
> there coudl be a generic .map file used by multiple of these tests. Would
> that make any sense? I see now that the map file has the names of the
> object files baked in, so I guess it doesn't make sense - unless the object
> files used the same names for each test and were put in a subdirectory,
> perhaps? (so there was foo/{1,2}.o, bar/{1,2}.o - and the map file would
> just mention 1.o and 2.o and could be reused for both the foo and bar tests)
>
>
>
> On Mon, Aug 3, 2015 at 3:39 PM, Frédéric Riss <friss at apple.com> wrote:
>
>> Here’s a new patch that refactors all the tests of the monolithic
>> odr-1.test into 3 different tests and hosts the CHECK lines with the source
>> code.
>> WDYT?
>>
>>
>>
>>
>>
>> On Jul 29, 2015, at 5:00 PM, David Blaikie <dblaikie at gmail.com> wrote:
>>
>>
>>
>> On Wed, Jul 29, 2015 at 3:58 PM, Frédéric Riss <friss at apple.com> wrote:
>>
>>>
>>> On Jul 29, 2015, at 3:35 PM, David Blaikie <dblaikie at gmail.com> wrote:
>>>
>>>
>>>
>>> On Wed, Jul 29, 2015 at 3:09 PM, Frédéric Riss <friss at apple.com> wrote:
>>>
>>>> How about the attached patch. It would go with the checked-in
>>>> odr-uniquing.o. This one just checks that all the basic types subject to
>>>> uniquing are actually uniqued (or not if the -no-odr flag is passed). It
>>>> requires only one object file because we can link it against itself using a
>>>> made up debug map.
>>>>
>>>
>>> Sounds pretty good.
>>>
>>> I certainly find it a bit more readable in this way (less checking,
>>> closer to the code, etc). It's still got a fair few cases, but not very out
>>> of character with other test cases we have.
>>>
>>> Would it be possible/reasonable to interleave the CHECK lines with the
>>> source code? Would save you having to have comments to describe the types
>>> next to the CHECK lines - they'd be self documenting. You might have to
>>> orchestrate the type emission order to match the source order with a bit of
>>> finagling?
>>>
>>>
>>> I started this way and then moved the CHECKs away from the code. One
>>> reason is that the typedef ends up being emitted last
>>>
>>
>> That's curious - I would've expected types to be emitted in the order
>> they are referenced by the variables in 'foo'.
>>
>> Oh, right, because all the class/struct types end up in the retained
>> types list due to DITypeRef stuff. And they all get emitted first because
>> we iterate the retained types first.
>>
>> So if you put the typedef after those, it'll be "in order"
>>
>>
>>> and I didn’t find a way to have the debug info match the source order (I
>>> didn’t try that hard though). The other reason is that the code became
>>> nearly invisible in-between the CHECKs. Having all the code together makes
>>> it IMO easier to read/search/refer to.
>>>
>>
>> I assume you use a syntax highlighting text editor? With that I usually
>> find it easy to see the alternating patches of code & comments, and
>> associate them together - the same as I do when reading source code with
>> detailed comments. Does this come out somewhat differently in terms of
>> readability?
>>
>>
>>>
>>> Some of your name checks are CHECK-NEXT after the TAG_*_type, while
>>> others use CHECK-NOT: NULL, then CHECK: for the name (presumably because
>>> there are attributes between the TAG and the name) - perhaps use the more
>>> general form for consistency & resilience to unimportant changes in
>>> attribute output from the tool?
>>>
>>>
>>> I did CHECK-NEXT each time I could, just because it save a line. I can
>>> move to always doing the CHECK-NOT dance, the test will just grow a bit.
>>>
>>
>> Yeah, I'm on the fence. I have a small preference towards resilience/not
>> relying on particular ordering of attribute output... but I know it becomes
>> more verbose. *shrug* your call (actually, so long as dsymutil preserves
>> the input attribute order, and you checkin binaries, you can depend on the
>> ordering without the tests being overly brittle - at least they're only
>> brittle to updates to the object file, which places the cost on you/the
>> dsymutil developers (that may exist in the future) - so the tests won't
>> break if we update LLVM to output in a different order, so it won't hurt
>> me, Adrian, etc, anyone else working on LLVM debug info - so that's not too
>> bad)
>>
>>
>>>
>>> It /might/ be smaller CHECK if you shared the checks for the variables
>>> and their types in 'foo' (putting them under CHECK, rather than ODR/NOODR)
>>> - to do that you'd need to use ODR/NOODR to check their original names.
>>>
>>> Something like:
>>>
>>> /* first CU */
>>> ODR: [[X]] structure_type
>>> NOODR: [[FIRST_X]] structure_type
>>> CHECK: name "foo"
>>> ...
>>> /* second CU */
>>> NOODR: [[X]] structure_type
>>> NOODR: name "foo"
>>>
>>> CHECK: variable
>>> CHECK: type [[X]]
>>>
>>> (this is only relevant because you aren't CHECKing the types of the
>>> variables in the first CU - which is OK, I suppose - they don't seem too
>>> interesting?) Not sure how much, if at all, better that might be?
>>>
>>>
>>> I need to try it. When I first wrote the test (the one that’s checked
>>> in), I started like that, but the differences where to big to share much.
>>> Now that I narrowed a bit the test, it might very well be worth
>>> re-exploring that possibility.
>>>
>>>
>> For the record, I tried it, and due to the order of emission (anonymous
>> namespace and typedef are emitted after the function that uses them), I
>> find it more natural the way it is. I could do that for half the variables,
>> but I prefer having a few more CHECK lines, but an overall CHECK structure
>> that’s totally coherent.
>>
>> Fred
>>
>> How's the tool handle the duplicate 'foo' function (that would be a link
>>> error in the actual object link)?
>>>
>>>
>>> The linker couldn’t generate that, but dsymutil doesn’t care (actually,
>>> the linker does generate such duplicate objects. Not with the same symbols,
>>> but the same object file might appear multiple times in LTO links. Don’t
>>> ask, I don’t know why. I need to figure that out.). llvm-dsymutil just
>>> works per-object applying the relocations described in the debug map. It
>>> doesn’t even need the symbol names most of the time.
>>>
>>> Other tests really requiring 2 or more object files would use what you
>>>> suggested with eg #ifdef FILE1/FILE2.
>>>>
>>>
>>> *nod* those were the ones I was sort of interested to see if/how they
>>> were, but at least the above seems like a good targeted test for the common
>>> cases, at least. Provide the common foundation & then the interesting
>>> things in separate tests, perhaps.
>>>
>>>
>>> I thought you’d say that :-) They won’t be that different than this one,
>>> except they’ll come with 2 (or maybe 3 for one of them) object files. If
>>> there are less checks, the CHECK lines might also fit better inside the
>>> code.
>>>
>>> I still want my higher-level integration tests, but I’ll find another
>>>> spot than LLVM for these :-)
>>>>
>>>
>>> Fair enough - might be worth making them fully end-to-end, from clang
>>> through to dlsym, etc.
>>>
>>>
>>> Yes, that’s the plan. And BTW, you keep calling it dlsym when it’s
>>> dsymutil. Either you have a pretty geeky auto-correct, or your muscle
>>> memory gives away your love of dynamic loader interfaces :-)
>>>
>>
>> Ah, right, thanks for the correction. Just my unfamiliarity with these
>> mac things. Will try to get that right.
>>
>> - Dave
>>
>>
>>>
>>> Thanks,
>>> Fred
>>>
>>>
>>>>
>>>>
>>>>
>>>> Fred
>>>>
>>>>
>>>> On Jul 27, 2015, at 2:47 PM, David Blaikie <dblaikie at gmail.com> wrote:
>>>>
>>>>
>>>>
>>>> On Mon, Jul 27, 2015 at 2:25 PM, Frédéric Riss <friss at apple.com> wrote:
>>>>
>>>>>
>>>>> On Jul 27, 2015, at 1:03 PM, David Blaikie <dblaikie at gmail.com> wrote:
>>>>>
>>>>>
>>>>>
>>>>> On Mon, Jul 27, 2015 at 12:33 PM, Frédéric Riss <friss at apple.com>
>>>>> wrote:
>>>>>
>>>>>> Reordering a bit the questions, because understanding the answer to
>>>>>> the last one is pretty crucial.
>>>>>>
>>>>>> The reason I did everything together, is to avoid recompiling odr1.ll
>>>>>>> multiple times and to avoid having to pattern match the contents of the
>>>>>>> DWARF for that file in every test. The story of the test in odr-1.test is:
>>>>>>>
>>>>>>> - compile all the odr[1-7].ll files into object files
>>>>>>> - using a dummy debug map,
>>>>>>>
>>>>>>
>>>>>> What's a debug map?
>>>>>>
>>>>>>
>>>>>> The debug map is the main input to the dwarf linker. It’s how it’s
>>>>>> called in the Darwin world, but the concept is pretty generic. It’s the
>>>>>> list of all the linked objects, and for each of these the list of linked
>>>>>> symbols (along with the link addresses). Usually, the debug map in embedded
>>>>>> into the executable by the linker in STABS format (it’s read inside
>>>>>> MachODebugMapParser.cpp in llvm-dsymutil). For testing llvm-dsymutil (but
>>>>>> also for help diagnosing issues in the field) I made the debug map
>>>>>> serializable in YAML. And these days, I’m using mostly YAML based debug
>>>>>> maps to test llvm-dsymutil.
>>>>>> You can’t just say link foo.o and bar.o together, because the linker
>>>>>> might have thrown some symbols away. These symbols (and their
>>>>>> dependencies)) must be stripped from the debug info.
>>>>>>
>>>>>
>>>>> Would it be worth it/handy to have a mapless mode for easy testing
>>>>> that just assumes nothing was thrown away?
>>>>>
>>>>>
>>>>> Possibly, but you’d still need a way to communicate which objects to
>>>>> link.
>>>>>
>>>>
>>>> I was thinking something like "if there are object files specified,
>>>> link them all together with a default map" (& treat any map files as
>>>> normal, ignoring any object files specified on the command line, etc) - but
>>>> I know very little about dlsym or its command line interface.
>>>>
>>>>
>>>>> I could add command line options for that purpose. I’ll think about
>>>>> it.
>>>>>
>>>>> On Jul 24, 2015, at 11:22 AM, David Blaikie <dblaikie at gmail.com>
>>>>>> wrote:
>>>>>> On Tue, Jul 21, 2015 at 5:02 PM, Frédéric Riss <friss at apple.com>
>>>>>> wrote:
>>>>>>
>>>>>>>
>>>>>>> On Jul 21, 2015, at 4:05 PM, David Blaikie <dblaikie at gmail.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Tue, Jul 21, 2015 at 3:41 PM, Frederic Riss <friss at apple.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> Author: friss
>>>>>>>> Date: Tue Jul 21 17:41:43 2015
>>>>>>>> New Revision: 242847
>>>>>>>>
>>>>>>>> URL: http://llvm.org/viewvc/llvm-project?rev=242847&view=rev
>>>>>>>> Log:
>>>>>>>> [dsymutil] Implement ODR uniquing for C++ code.
>>>>>>>>
>>>>>>>> This optimization allows the DWARF linker to reuse definition of
>>>>>>>> types it has emitted in previous CUs rather than reemitting them
>>>>>>>> in each CU that references them. The size and link time gains are
>>>>>>>> huge. For example when linking the DWARF for a debug build of
>>>>>>>> clang, this generates a ~150M dwarf file instead of a ~700M one
>>>>>>>> (the numbers date back a bit and must not be totally accurate
>>>>>>>> these days).
>>>>>>>>
>>>>>>>> As with all the other parts of the llvm-dsymutil codebase, the
>>>>>>>> goal is to keep bit-for-bit compatibility with dsymutil-classic.
>>>>>>>> The code is littered with a lot of FIXMEs that should be
>>>>>>>> addressed once we can get rid of the compatibilty goal.
>>>>>>>>
>>>>>>>
>>>>>>> Did dsymutil-classic do this ODR uniquing too? (not quite clear to
>>>>>>> me from your description here - where you mention compatibility, etc) How
>>>>>>> does its implementation compare?
>>>>>>>
>>>>>>>
>>>>>>> Yes it existed, but it wasn’t enabled by default before Xcode 7 (I
>>>>>>> actually wonder if it found its way into any previous release). But it was
>>>>>>> definitely there when I started llvm-dsymutil. The dsymutil-classic and
>>>>>>> llvm-dsymutil that come with Xcode 7 have it both enabled by default and
>>>>>>> should be bit-for-bit compatible (this has been tested for every dSYM
>>>>>>> bundle that our internal build system generates).
>>>>>>>
>>>>>>
>>>>>> Do you mean bit-for-bit identical? Or compatible in some way (such as
>>>>>> "doesn't require changes to the debug info consumers on the platform" to
>>>>>> pass <some tests>?)? Or something else?
>>>>>>
>>>>>>
>>>>>> Bit-for-bit identical. At least for a start. That’s how we tested
>>>>>> that there would be no regression for users (It allowed to compare outputs
>>>>>> using a simple ‘cpp’ command. Otherwise comparing debug-info is really
>>>>>> hard). We tested the bit-for-bit compatibility on all the internal
>>>>>> codebases for both OS X and iOS. I want to keep that goal for now, as I’d
>>>>>> like to be able to relaunch one such validation campaign once I have
>>>>>> everything upstreamed. After that I can start breaking compatibility and
>>>>>> removing the FIXMEs in the code.
>>>>>>
>>>>>>
>>>>>>>
>>>>>>>> Added:
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr-types.h
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr1.cpp
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr1.ll
>>>>>>>>
>>>>>>>
>>>>>>> Might be useful to have more distinguishing names for the test files
>>>>>>> here? (I assume each ODR test only needs two files - or do some need more
>>>>>>> than that?)
>>>>>>>
>>>>>>>
>>>>>>> The tests are mostly between what’s in odr1.o and each every other
>>>>>>> file.
>>>>>>>
>>>>>>
>>>>>> So parts of odr1 are used in various odin?
>>>>>>
>>>>>>
>>>>>> Yes. odr1, is first used again itself (using a forged debug map) to
>>>>>> see that everything gets unique. Then the various other odr* files are
>>>>>> linked to test special cases that needed to be in different files.
>>>>>>
>>>>>> (side note: why is the IR checked in, rather than built object files?
>>>>>> Given that the C++ source is provided, does the IR provide much else here?)
>>>>>>
>>>>>>
>>>>>> I’m pretty proud of that :-) I think that if we can avoid committing
>>>>>> binaries, we should do so.
>>>>>>
>>>>>
>>>>> In general, I agree.
>>>>>
>>>>>
>>>>>> I have a bunch of binaries checked in, because there are things you
>>>>>> just can’t test without that, but for most tests now I prefer to generate
>>>>>> the object files from IR. Some of the other advantages I see:
>>>>>>  - These are easier to augment with new cases (when I modify the ODR
>>>>>> implementation or when we find bugs).
>>>>>>
>>>>>
>>>>> How so? You still have to update the source code, regenerate the IR
>>>>> and regenerate the object files? Not having the IR checked in seems like
>>>>> it'd simplify updates to the test cases, not complicate it.
>>>>>
>>>>>
>>>>> The object files aren’t checked in. I generate them within the test
>>>>> from the IR.
>>>>>
>>>>
>>>> Ah, right - sorry, didn't have that all clear in my head.
>>>>
>>>>
>>>>> One thing I definitely want to avoid is updates to checked-in object
>>>>> files.
>>>>>
>>>>
>>>> From my perspective, that's the contract of dlsym "given these object
>>>> files/debug map, expect this output" - testing anything else is out of
>>>> scope & makes the tests brittle.
>>>>
>>>> LLVM isn't perfect about this, for sure - but we generally try to
>>>> isolate tests to make debugging and updating tests easier. The IR
>>>> parser/writer are certainly an exception - but testing the whole
>>>> codegen/debug info generation path when testing dlsym. The same reason we
>>>> don't test debug info object output in Clang, for example - we just test
>>>> that the right IR came out. (& don't test LLVM's behavior on Clang's (live)
>>>> output in LLVM's tests - which is a more accurate comparison & the project
>>>> structure enforces that separation, but it'd be an intentional choice, even
>>>> if it weren't blocked by that boundary)
>>>>
>>>>
>>>>>
>>>>>  - debug info IR changes will be tested right-away with llvm-dsymutil
>>>>>>
>>>>>
>>>>> This, I think, is unfortunate - debug info IR should be tested in
>>>>> LLVM. Having it exposed elsewhere makes it brittle when updating things -
>>>>> it means updates to LLVM IR break the dsymutil tests when dsymutil doesn't
>>>>> actually depend on the textual IR at all.
>>>>>
>>>>>
>>>>> llvm-dsymutil might not care about the textual IR, but it obviously
>>>>> cares about the emitted DWARF.
>>>>>
>>>>
>>>> As LLVM cares about Clang's IR output (for debug info or just all the
>>>> normal code generation). Yet we test separately up to that boundary in
>>>> Clang, and beyond the boundary in LLVM - not across the boundary.
>>>>
>>>>
>>>>>  I’m not only thinking about updates to the textual IR, but also for
>>>>> example changes in the order we emit things, or in the type of relocations
>>>>> we emit, adding a new DW_AT_artificial to some member, … (i.e.. I care more
>>>>> about semantics than syntax). Regenerating the object file with llc allows
>>>>> these kind of (semantic) changes to be directly tested by one of the
>>>>> consumers of debug info. My thinking is that I don’t want some addition to
>>>>> our debug info representation to break dsymutil without it getting noticed.
>>>>> Of course I’m happy to handle any fallout of such changes, but I want to be
>>>>> able to make sure that they don’t actually matter.
>>>>>
>>>>>
>>>>>
>>>>>>  - It makes it pretty clear what’s in the output. While a discrepancy
>>>>>> between the source and the IR can happen, the IR makes it clear what to
>>>>>> expect in the .o file without resorting to any binary inspection tool.
>>>>>>
>>>>>
>>>>> Perhaps - but if there are discrepancies between the source and
>>>>> object, then equally there can be discrepancies between IR and object -
>>>>> adding another input to "vote" on which is correct doesn't seem like it
>>>>> adds a lot of value.
>>>>>
>>>>>
>>>>>> I'm wondering if we could use a more isolated approach rather than
>>>>>> test cases that seem to exercise several different things across many
>>>>>> files. Something more like:
>>>>>>
>>>>>> // The checked in object files were produced by:
>>>>>> // compile -DOTHER -o testname-a.o
>>>>>> // compile testname-b.o
>>>>>> // CHECK: dsymutil testname-a.o testname-b.o | dwarfdump | FileCheck
>>>>>>
>>>>>> struct foo {
>>>>>> };
>>>>>> namespace {
>>>>>> struct bar {
>>>>>> }
>>>>>> };
>>>>>>
>>>>>> #ifdef OTHER
>>>>>> foo f1;
>>>>>> bar b1;
>>>>>> #else
>>>>>> foo f2;
>>>>>> bar b2;
>>>>>> #endif
>>>>>>
>>>>>> // CHECK: that foo is defined once, bar is defined twice, and
>>>>>> f1/b1/f2/b2 reference those definitions
>>>>>>
>>>>>>
>>>>>> dsymutil doesn’t take .o files as input, but a debug map. I chose to
>>>>>> put the CHECK lines in the debug map because I think it make more sense
>>>>>> there (And use only one test file to avoid having to re-match the contents
>>>>>> of odr1.o in every test).
>>>>>>
>>>>>
>>>>> I'm suggesting not having a universal file like odr1 - by having the
>>>>> source near the check lines and only having the relevant source for each
>>>>> test case there wouldn't be so much redundant matching so it'd be easy-ish
>>>>> to have them separated.
>>>>>
>>>>>
>>>>> While I see your point, I think there’s not too much to split. The
>>>>> types being declared in the same file is part of the test. I wanted a
>>>>> single global context that contains types with the same name (here mostly S
>>>>> and C) redefined in multiple contexts with different meanings (::S, ::N::C,
>>>>> ::N::N::C, ::U::S, ::U::C) to make sure that dsymutil doesn’t confuse them.
>>>>>
>>>>
>>>> Sure - but this kind of broad testing can make tests hard to
>>>> follow/understand. Is there something about the design of your code that
>>>> means, for example, the ::N::N::C case is interesting? What's the
>>>> interesting codepath that that covers that isn't covered by ::N::C? (or
>>>> ::C/::S?)
>>>>
>>>> By having each test case separated, to some degree (certainly in LLVM
>>>> and Clang we have test files with multiple test cases - but, usually, we
>>>> can keep the input and the expected output (CHECK) lines together (debug
>>>> info tests don't fit this model perfectly - which is why we tend towards
>>>> more fine-grained debug info tests (and debug info metadata or DWARF is
>>>> verbose, so having lots in one file becomes unweildy))) it can be easier to
>>>> understand the justification for each one rather than "here's a whole bunch
>>>> of stuff that should be correct".
>>>>
>>>>
>>>>> As to having the comments closer the the source, more on that bellow.
>>>>>
>>>>> I found no way to put the debug map in the same file as any of the
>>>>>> other inputs (I definitely thought about that, but the only thing that came
>>>>>> to mind was to invent some container format to package IR and YAML
>>>>>> together.)
>>>>>>
>>>>>
>>>>> Could possibly use a common, single debug map that just lists a single
>>>>> symbol that's in all files? (I guess not, because you wanted to test things
>>>>> like implicit ctors, etc - in which case see the earlier question about
>>>>> possibly having a test-convenience no-map version that just assumes all
>>>>> symbols are emitted?)
>>>>>
>>>>>
>>>>> odr-1.test is basically that single debug map you’re referring to. It
>>>>> lists all the files and the interesting symbols in each of them.
>>>>>
>>>>
>>>> Right, sorry, I meant a single debug map that would be the same for
>>>> every file/test, so it would be uninteresting background like "oh, every
>>>> test includes a 'foo' function, because that's the debug info anchor point".
>>>>
>>>>
>>>>>
>>>>> In any case, even if the maps were included - they seem
>>>>> incidental/mostly a side-effect, not the core thing that's being tested, so
>>>>> keeping the CHECK lines near the source/features being tested would make
>>>>> the tests easier for me to read, at least.
>>>>>
>>>>>
>>>>> I agree that the maps aren’t what is being tested. But at least they
>>>>> are part of the link process. The alternative would be to put the sources
>>>>> in the test directory and the maps in the Inputs directory.
>>>>>
>>>>
>>>> Strangely, that may be more consistent (especially if you end up with
>>>> checked in object files) - the map is the input to the linker, not the
>>>> object files. But that's just a silly technicality/semantic argument.
>>>>
>>>>
>>>>> It just seemed much more logical to me to have the sources alongside
>>>>> their derived IR files in the Inputs directory and to use the map (that’s
>>>>> actually part of the link command) as the test file. But I’m not against
>>>>> changing that. I’d need to play around with the idea to see how the tests
>>>>> look like. It just seems odd to have the source in the test directory and
>>>>> the IR in the Inputs directory. I’d need to add a comment to the generated
>>>>> IRs to point to the location of the source.
>>>>>
>>>>
>>>> If they're consistently named, I wouldn't worry about adding comments
>>>> (foo.cpp, Inputs/foo-1.ll, Inputs/foo-2.ll) I think we have test cases like
>>>> this, for example, for LTO debug info in LLVM maybe?
>>>>
>>>>
>>>>>
>>>>>
>>>>>> (or this could even be two separate tests, one for anonymous
>>>>>> namespaced types, one for external types, etc - same sort of thing we do in
>>>>>> other tests, where we group some related things together, but while keeping
>>>>>> more of the information together so the checks are more legible because you
>>>>>> can see the scenario they're trying to check. Spreading a single set of
>>>>>> CHECKs across 8 files and a header makes it a bit difficult to follow -
>>>>>> reading the CHECK lines and then trying to consult all the files to see
>>>>>> what it should be)
>>>>>>
>>>>>>
>>>>>> As I said above, the link is debug map based, so the CHECK lines are
>>>>>> stored with the YAML debug map. I could have done a few things differently,
>>>>>> but considering that any test for the ODR uniquing involves at least 3
>>>>>> files (2 object files and the debug map), I did my best to keep things as
>>>>>> condensed as possible.
>>>>>>
>>>>>>
>>>>>>
>>>>>>> Some of them require more though for example odr6 and 7 (see
>>>>>>> specifics below) are separate on purpose, because want to check that the
>>>>>>> result of the odr7 link didn’t reuse the odr6 results.
>>>>>>>
>>>>>>> I see it's all in odr-1.test - it's a bit monolithic, isn't it? I'm
>>>>>>> not sure I understand the motivation for 7 different inputs and then
>>>>>>> checking all together. Could you explain it?
>>>>>>>
>>>>>>>
>>>>>>> You can see in the name (odr-*1*.test) that I initially planned on
>>>>>>> having multiple tests. However, I found it easier to put everything in the
>>>>>>> same file (which is big, I agree, but it’s also pretty well commented if
>>>>>>> one understands what it’s talking about :-)).
>>>>>>>
>>>>>>
>>>>>> The big test file says things like "this is class N::C" - that
>>>>>> doesn't mean much to me as a reader without going through all the source
>>>>>> files to see how it is used and referenced.
>>>>>>
>>>>>> "this is a lambda inside func" - if I could see the source, that
>>>>>> would be helpful. But as it is I don't know what interesting property
>>>>>> you're trying to test for in that thing - that it's not duplicated? That it
>>>>>> is?
>>>>>>
>>>>>>
>>>>>> Reading linearly through the test file, the comments and structure
>>>>>> read this way:
>>>>>> # Totally made up debug map to test ODR uniquing
>>>>>> <debug map part pulling odr1.o>
>>>>>> # Check that all our types are in the first CU.
>>>>>> < DWARF matching for odr1 CU>
>>>>>> # This is "struct S”
>>>>>> < DWARF for struct S>
>>>>>> # This is "class N::C"
>>>>>> < DWARF for N::C>
>>>>>> # This is "class N::N::C"
>>>>>> < DWARF for N::N::C>
>>>>>> # This is "AliasForS"
>>>>>> < DWARF for AliasForS>
>>>>>> < DWARF and comments for the rest of odr1.o>
>>>>>>
>>>>>> < Debug map part pulling in odr1.o again>
>>>>>> # We relink the same file a second time. In the ODR case, everything
>>>>>> (except for the
>>>>>> # union for now) should be uniqued. In the non-ODR case, we should
>>>>>> get every type
>>>>>> # duplicated.
>>>>>> < DWARF and comments for the uniqued version of odr1.o
>>>>>>
>>>>>> < debug map pulling in odr2.o and odr3.o>
>>>>>> # odr2.cpp and odr3.cpp test that a simple overloaded function
>>>>>> doesn't break the
>>>>>> # uniquing (contrary to what we'll see with template/artificial)
>>>>>> functions.
>>>>>> < DWARF for odr2 and odr3>
>>>>>>
>>>>>> <etc…>
>>>>>>
>>>>>> I honestly think these are pretty awesome comments.
>>>>>>
>>>>>
>>>>> As a new reader to this file - how do you make sense of the checks and
>>>>> their comments? It's pretty hard to tell what the entities are that the
>>>>> comments are referring to For example:
>>>>>
>>>>>
>>>>> I'm not sure why there's a double-nested namespace N (what codepath
>>>>> does that test that a single level of namespacing (or none?) wouldn't?)
>>>>>
>>>>>
>>>>> As I said above this is more above not confusing something called N::C
>>>>> in 2 different contexts. To be honest, the types in odr1 were mostly about
>>>>> getting a bit of every unique-able stuff, while the tests in odr2-7 are
>>>>> more about getting code coverage of corner cases.
>>>>>
>>>>
>>>> Which is perhaps adding to the confusion I'm having - the types are
>>>> used for multiple things so they may have superfluous features for one
>>>> thing or the other, which adds complexity when trying to understand one
>>>> particular test case in isolation.
>>>>
>>>>
>>>>>
>>>>> The descriptions of code in the comments seem like they're a stand-in
>>>>> for being able to read the code itself/having it nearby. Mostly the code is
>>>>> short enough that if it were nearby it'd be fairly self documenting, or at
>>>>> least add a bit of extra detail in cases where the comments may not be
>>>>> sufficient.
>>>>>
>>>>>
>>>>> And I’ll try to play with that idea. I’m just interested in your
>>>>> feeling about the source vs derived files location thing.
>>>>>
>>>>> (side note, while looking through the comments I came across "contrary
>>>>> to what we'll see with template/artificial" - I guess what you want there
>>>>> is "contrary to what we'll see with inline functions" (implicit special
>>>>> members and implicit template specializations are interesting ways that
>>>>> inline functions arise - but normal inline functions are the more
>>>>> obvious/common case and the term "inline function" describes all of these
>>>>> things)?)
>>>>>
>>>>>
>>>>> For templates and implicit special members, their DW_TAG_subprogram
>>>>> will only be added to the type when they are codegened (generating a new
>>>>> non-uniquable version of the type in the process). I would have expected
>>>>> the DISubprogram for an inline member to be included in the type (but not
>>>>> referenced by any DW_AT_specification in that CU), but maybe I’m wrong?
>>>>>
>>>>
>>>> Ah, no, you're right - if it's specifically about member functions, not
>>>> free functions - implicit special members, implicit member function
>>>> template specializations.
>>>>
>>>> You might want to also add nested types to that? Check the debug info
>>>> for something like this:
>>>>
>>>> struct foo {
>>>> struct bar;
>>>> };
>>>>
>>>> ...
>>>>
>>>> struct foo::bar { // put this in one file using 'foo' and link it with
>>>> another file (without this definition) that also uses 'foo'
>>>> };
>>>>
>>>>
>>>>
>>>>
>>>>>
>>>>> Just trying to describe how I read/look at this test & the
>>>>> difficulties I find with understanding it... perhaps other people have
>>>>> other ideas about the ease with which they can understand them.
>>>>>
>>>>>
>>>>> And I’m happy to take your feedback into account :-)
>>>>>
>>>>> Fred
>>>>>
>>>>> - David
>>>>>
>>>>>
>>>>>> As for all the other tests, you need some really good understanding
>>>>>> of what’s supposed to go on in the first place though. But I definitely
>>>>>> invested time in trying to make them more palatable.
>>>>>>
>>>>>> Fred
>>>>>>
>>>>>>
>>>>>>
>>>>>>> The reason I did everything together, is to avoid recompiling
>>>>>>> odr1.ll multiple times and to avoid having to pattern match the contents of
>>>>>>> the DWARF for that file in every test. The story of the test in odr-1.test
>>>>>>> is:
>>>>>>>
>>>>>>> - compile all the odr[1-7].ll files into object files
>>>>>>> - using a dummy debug map,
>>>>>>>
>>>>>>
>>>>>> What's a debug map?
>>>>>>
>>>>>>
>>>>>>> link all these together (including linking odr1.o twice) once with
>>>>>>> ODR uniquing and once without
>>>>>>> - The odr1.ll file instantiates all the types contained in
>>>>>>> odr-types.h, thus its debug info will contain all the definitions. This is
>>>>>>> basically the ODR context pool that should be reused
>>>>>>> - Then the other odr*.ll that have been linked are tested like this:
>>>>>>>   * odr1.o is linked a second time, and I check that no types
>>>>>>> (except for one corner case) have been duplicated and that everything links
>>>>>>> to the first CU
>>>>>>>   * odr2.o and odr3.o both instantiate a different version of an
>>>>>>> overloaded inline function. We test that both these CUs do not contain a
>>>>>>> copy of the corresponding type and that uniquing was applied correctly.
>>>>>>>   * odr4.o checks that we do not unique different thing with the
>>>>>>> same name inside anonymous namespaces
>>>>>>>   * odr5.o and odr6.o are similar to 2/3, except that they
>>>>>>> instantiate a template member function. These ones can’t be uniqued with
>>>>>>> the content in odr1.o because the type is extended with a different member
>>>>>>> function each time.
>>>>>>>   * odr7.o checks that we can correctly reference directly a nested
>>>>>>> type.
>>>>>>>
>>>>>>> I could definitely merge some of the unrelated ones together (say 2
>>>>>>> 4 and 7), it just seemed nice that each one tackled a slightly different
>>>>>>> issue. I could have named them according to their contents though. Would
>>>>>>> you like that I rename them? Or I could merge some of them, but then
>>>>>>> renaming make less sense.
>>>>>>>
>>>>>>> Fred
>>>>>>>
>>>>>>> - Dave
>>>>>>>
>>>>>>>
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr2.cpp
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr2.ll
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr3.cpp
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr3.ll
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr4.cpp
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr4.ll
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr5.cpp
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr5.ll
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr6.cpp
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr6.ll
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr7.cpp
>>>>>>>>     llvm/trunk/test/tools/dsymutil/Inputs/odr7.ll
>>>>>>>>     llvm/trunk/test/tools/dsymutil/X86/odr-1.test
>>>>>>>> Modified:
>>>>>>>>     llvm/trunk/tools/dsymutil/DwarfLinker.cpp
>>>>>>>>     llvm/trunk/tools/dsymutil/dsymutil.cpp
>>>>>>>>     llvm/trunk/tools/dsymutil/dsymutil.h
>>>>>>>>
>>>>>>>> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr-types.h
>>>>>>>> URL:
>>>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr-types.h?rev=242847&view=auto
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- llvm/trunk/test/tools/dsymutil/Inputs/odr-types.h (added)
>>>>>>>> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr-types.h Tue Jul 21
>>>>>>>> 17:41:43 2015
>>>>>>>> @@ -0,0 +1,51 @@
>>>>>>>> +struct S {
>>>>>>>> +       int I;
>>>>>>>> +
>>>>>>>> +       void incr() __attribute__((always_inline)) { I++; }
>>>>>>>> +       void incr(int Add) __attribute__((always_inline)) { I +=
>>>>>>>> Add; }
>>>>>>>> +
>>>>>>>> +       typedef int SInt;
>>>>>>>> +
>>>>>>>> +       struct Nested {
>>>>>>>> +               double D;
>>>>>>>> +
>>>>>>>> +               template<typename T> void init(T Val) { D =
>>>>>>>> double(Val); }
>>>>>>>> +       };
>>>>>>>> +
>>>>>>>> +       Nested D;
>>>>>>>> +
>>>>>>>> +public:
>>>>>>>> +       int foo() { return I; }
>>>>>>>> +};
>>>>>>>> +
>>>>>>>> +typedef S AliasForS;
>>>>>>>> +
>>>>>>>> +namespace N {
>>>>>>>> +class C {
>>>>>>>> +       AliasForS S;
>>>>>>>> +};
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +namespace N {
>>>>>>>> +namespace N {
>>>>>>>> +class C {
>>>>>>>> +        int S;
>>>>>>>> +};
>>>>>>>> +}
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +namespace {
>>>>>>>> +       class AnonC {
>>>>>>>> +       };
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +union U {
>>>>>>>> +       class C {} C;
>>>>>>>> +       struct S {} S;
>>>>>>>> +};
>>>>>>>> +
>>>>>>>> +inline int func() {
>>>>>>>> +       struct CInsideFunc { int i; };
>>>>>>>> +       auto functor = []() { CInsideFunc dummy; return dummy.i; };
>>>>>>>> +       return functor();
>>>>>>>> +}
>>>>>>>>
>>>>>>>> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr1.cpp
>>>>>>>> URL:
>>>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr1.cpp?rev=242847&view=auto
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- llvm/trunk/test/tools/dsymutil/Inputs/odr1.cpp (added)
>>>>>>>> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr1.cpp Tue Jul 21
>>>>>>>> 17:41:43 2015
>>>>>>>> @@ -0,0 +1,11 @@
>>>>>>>> +#include "odr-types.h"
>>>>>>>> +
>>>>>>>> +int foo() {
>>>>>>>> +       AliasForS s;
>>>>>>>> +       N::C nc;
>>>>>>>> +       N::N::C nnc;
>>>>>>>> +       AnonC ac;
>>>>>>>> +       U u;
>>>>>>>> +
>>>>>>>> +       return func();
>>>>>>>> +}
>>>>>>>>
>>>>>>>> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr1.ll
>>>>>>>> URL:
>>>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr1.ll?rev=242847&view=auto
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- llvm/trunk/test/tools/dsymutil/Inputs/odr1.ll (added)
>>>>>>>> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr1.ll Tue Jul 21
>>>>>>>> 17:41:43 2015
>>>>>>>> @@ -0,0 +1,153 @@
>>>>>>>> +; Generated from odr1.cpp and odr-types.h by running:
>>>>>>>> +; clang -emit-llvm -g -S -std=c++11 odr1.cpp
>>>>>>>> +; ModuleID = 'odr1.cpp'
>>>>>>>> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>>>>>>>> +target triple = "x86_64-apple-macosx10.11.0"
>>>>>>>> +
>>>>>>>> +%struct.S = type { i32, %"struct.S::Nested" }
>>>>>>>> +%"struct.S::Nested" = type { double }
>>>>>>>> +%"class.N::C" = type { %struct.S }
>>>>>>>> +%"class.N::N::C" = type { i32 }
>>>>>>>> +%"class.(anonymous namespace)::AnonC" = type { i8 }
>>>>>>>> +%union.U = type { %"class.U::C" }
>>>>>>>> +%"class.U::C" = type { i8 }
>>>>>>>> +%class.anon = type { i8 }
>>>>>>>> +%struct.CInsideFunc = type { i32 }
>>>>>>>> +
>>>>>>>> +; Function Attrs: ssp uwtable
>>>>>>>> +define i32 @_Z3foov() #0 {
>>>>>>>> +entry:
>>>>>>>> +  %s = alloca %struct.S, align 8
>>>>>>>> +  %nc = alloca %"class.N::C", align 8
>>>>>>>> +  %nnc = alloca %"class.N::N::C", align 4
>>>>>>>> +  %ac = alloca %"class.(anonymous namespace)::AnonC", align 1
>>>>>>>> +  %u = alloca %union.U, align 1
>>>>>>>> +  call void @llvm.dbg.declare(metadata %struct.S* %s, metadata
>>>>>>>> !59, metadata !60), !dbg !61
>>>>>>>> +  call void @llvm.dbg.declare(metadata %"class.N::C"* %nc,
>>>>>>>> metadata !62, metadata !60), !dbg !63
>>>>>>>> +  call void @llvm.dbg.declare(metadata %"class.N::N::C"* %nnc,
>>>>>>>> metadata !64, metadata !60), !dbg !65
>>>>>>>> +  call void @llvm.dbg.declare(metadata %"class.(anonymous
>>>>>>>> namespace)::AnonC"* %ac, metadata !66, metadata !60), !dbg !69
>>>>>>>> +  call void @llvm.dbg.declare(metadata %union.U* %u, metadata !70,
>>>>>>>> metadata !60), !dbg !71
>>>>>>>> +  %call = call i32 @_Z4funcv(), !dbg !72
>>>>>>>> +  ret i32 %call, !dbg !73
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +; Function Attrs: nounwind readnone
>>>>>>>> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
>>>>>>>> +
>>>>>>>> +; Function Attrs: inlinehint ssp uwtable
>>>>>>>> +define linkonce_odr i32 @_Z4funcv() #2 {
>>>>>>>> +entry:
>>>>>>>> +  %functor = alloca %class.anon, align 1
>>>>>>>> +  call void @llvm.dbg.declare(metadata %class.anon* %functor,
>>>>>>>> metadata !74, metadata !60), !dbg !75
>>>>>>>> +  %call = call i32 @_ZZ4funcvENKUlvE_clEv(%class.anon* %functor),
>>>>>>>> !dbg !76
>>>>>>>> +  ret i32 %call, !dbg !77
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +; Function Attrs: inlinehint nounwind ssp uwtable
>>>>>>>> +define linkonce_odr i32 @_ZZ4funcvENKUlvE_clEv(%class.anon* %this)
>>>>>>>> #3 align 2 {
>>>>>>>> +entry:
>>>>>>>> +  %this.addr = alloca %class.anon*, align 8
>>>>>>>> +  %dummy = alloca %struct.CInsideFunc, align 4
>>>>>>>> +  store %class.anon* %this, %class.anon** %this.addr, align 8
>>>>>>>> +  call void @llvm.dbg.declare(metadata %class.anon** %this.addr,
>>>>>>>> metadata !78, metadata !60), !dbg !80
>>>>>>>> +  %this1 = load %class.anon*, %class.anon** %this.addr
>>>>>>>> +  call void @llvm.dbg.declare(metadata %struct.CInsideFunc*
>>>>>>>> %dummy, metadata !81, metadata !60), !dbg !82
>>>>>>>> +  %i = getelementptr inbounds %struct.CInsideFunc,
>>>>>>>> %struct.CInsideFunc* %dummy, i32 0, i32 0, !dbg !83
>>>>>>>> +  %0 = load i32, i32* %i, align 4, !dbg !83
>>>>>>>> +  ret i32 %0, !dbg !84
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +attributes #0 = { ssp uwtable "disable-tail-calls"="false"
>>>>>>>> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
>>>>>>>> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
>>>>>>>> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
>>>>>>>> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
>>>>>>>> "unsafe-fp-math"="false" "use-soft-float"="false" }
>>>>>>>> +attributes #1 = { nounwind readnone }
>>>>>>>> +attributes #2 = { inlinehint ssp uwtable
>>>>>>>> "disable-tail-calls"="false" "less-precise-fpmad"="false"
>>>>>>>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"
>>>>>>>> "no-infs-fp-math"="false" "no-nans-fp-math"="false"
>>>>>>>> "stack-protector-buffer-size"="8" "target-cpu"="core2"
>>>>>>>> "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false"
>>>>>>>> "use-soft-float"="false" }
>>>>>>>> +attributes #3 = { inlinehint nounwind ssp uwtable
>>>>>>>> "disable-tail-calls"="false" "less-precise-fpmad"="false"
>>>>>>>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"
>>>>>>>> "no-infs-fp-math"="false" "no-nans-fp-math"="false"
>>>>>>>> "stack-protector-buffer-size"="8" "target-cpu"="core2"
>>>>>>>> "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false"
>>>>>>>> "use-soft-float"="false" }
>>>>>>>> +
>>>>>>>> +!llvm.dbg.cu = !{!0}
>>>>>>>> +!llvm.module.flags = !{!55, !56, !57}
>>>>>>>> +!llvm.ident = !{!58}
>>>>>>>> +
>>>>>>>> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file:
>>>>>>>> !1, producer: "clang version 3.8.0 (trunk 242534)", isOptimized: false,
>>>>>>>> runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !3,
>>>>>>>> subprograms: !52)
>>>>>>>> +!1 = !DIFile(filename: "odr1.cpp", directory: "/Inputs")
>>>>>>>> +!2 = !{}
>>>>>>>> +!3 = !{!4, !20, !24, !29, !33, !37, !38, !39, !49}
>>>>>>>> +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", file:
>>>>>>>> !5, line: 1, size: 128, align: 64, elements: !6, identifier: "_ZTS1S")
>>>>>>>> +!5 = !DIFile(filename: "./odr-types.h", directory: "/Inputs")
>>>>>>>> +!6 = !{!7, !9, !10, !14, !17}
>>>>>>>> +!7 = !DIDerivedType(tag: DW_TAG_member, name: "I", scope:
>>>>>>>> !"_ZTS1S", file: !5, line: 2, baseType: !8, size: 32, align: 32)
>>>>>>>> +!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding:
>>>>>>>> DW_ATE_signed)
>>>>>>>> +!9 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
>>>>>>>> !"_ZTS1S", file: !5, line: 15, baseType: !"_ZTSN1S6NestedE", size: 64,
>>>>>>>> align: 64, offset: 64)
>>>>>>>> +!10 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEv",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 4, type: !11, isLocal: false,
>>>>>>>> isDefinition: false, scopeLine: 4, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false)
>>>>>>>> +!11 = !DISubroutineType(types: !12)
>>>>>>>> +!12 = !{null, !13}
>>>>>>>> +!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType:
>>>>>>>> !"_ZTS1S", size: 64, align: 64, flags: DIFlagArtificial |
>>>>>>>> DIFlagObjectPointer)
>>>>>>>> +!14 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEi",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 5, type: !15, isLocal: false,
>>>>>>>> isDefinition: false, scopeLine: 5, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false)
>>>>>>>> +!15 = !DISubroutineType(types: !16)
>>>>>>>> +!16 = !{null, !13, !8}
>>>>>>>> +!17 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false,
>>>>>>>> isDefinition: false, scopeLine: 18, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false)
>>>>>>>> +!18 = !DISubroutineType(types: !19)
>>>>>>>> +!19 = !{!8, !13}
>>>>>>>> +!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "Nested",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 9, size: 64, align: 64, elements: !21,
>>>>>>>> identifier: "_ZTSN1S6NestedE")
>>>>>>>> +!21 = !{!22}
>>>>>>>> +!22 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
>>>>>>>> !"_ZTSN1S6NestedE", file: !5, line: 10, baseType: !23, size: 64, align: 64)
>>>>>>>> +!23 = !DIBasicType(name: "double", size: 64, align: 64, encoding:
>>>>>>>> DW_ATE_float)
>>>>>>>> +!24 = !DICompositeType(tag: DW_TAG_class_type, name: "C", scope:
>>>>>>>> !25, file: !5, line: 24, size: 128, align: 64, elements: !26, identifier:
>>>>>>>> "_ZTSN1N1CE")
>>>>>>>> +!25 = !DINamespace(name: "N", scope: null, file: !5, line: 23)
>>>>>>>> +!26 = !{!27}
>>>>>>>> +!27 = !DIDerivedType(tag: DW_TAG_member, name: "S", scope:
>>>>>>>> !"_ZTSN1N1CE", file: !5, line: 25, baseType: !28, size: 128, align: 64)
>>>>>>>> +!28 = !DIDerivedType(tag: DW_TAG_typedef, name: "AliasForS", file:
>>>>>>>> !5, line: 21, baseType: !"_ZTS1S")
>>>>>>>> +!29 = !DICompositeType(tag: DW_TAG_class_type, name: "C", scope:
>>>>>>>> !30, file: !5, line: 31, size: 32, align: 32, elements: !31, identifier:
>>>>>>>> "_ZTSN1N1N1CE")
>>>>>>>> +!30 = !DINamespace(name: "N", scope: !25, file: !5, line: 30)
>>>>>>>> +!31 = !{!32}
>>>>>>>> +!32 = !DIDerivedType(tag: DW_TAG_member, name: "S", scope:
>>>>>>>> !"_ZTSN1N1N1CE", file: !5, line: 32, baseType: !8, size: 32, align: 32)
>>>>>>>> +!33 = !DICompositeType(tag: DW_TAG_union_type, name: "U", file:
>>>>>>>> !5, line: 42, size: 8, align: 8, elements: !34, identifier: "_ZTS1U")
>>>>>>>> +!34 = !{!35, !36}
>>>>>>>> +!35 = !DIDerivedType(tag: DW_TAG_member, name: "C", scope:
>>>>>>>> !"_ZTS1U", file: !5, line: 43, baseType: !"_ZTSN1U1CE", size: 8, align: 8)
>>>>>>>> +!36 = !DIDerivedType(tag: DW_TAG_member, name: "S", scope:
>>>>>>>> !"_ZTS1U", file: !5, line: 44, baseType: !"_ZTSN1U1SE", size: 8, align: 8)
>>>>>>>> +!37 = !DICompositeType(tag: DW_TAG_class_type, name: "C", scope:
>>>>>>>> !"_ZTS1U", file: !5, line: 43, size: 8, align: 8, elements: !2, identifier:
>>>>>>>> "_ZTSN1U1CE")
>>>>>>>> +!38 = !DICompositeType(tag: DW_TAG_structure_type, name: "S",
>>>>>>>> scope: !"_ZTS1U", file: !5, line: 44, size: 8, align: 8, elements: !2,
>>>>>>>> identifier: "_ZTSN1U1SE")
>>>>>>>> +!39 = !DICompositeType(tag: DW_TAG_class_type, scope: !40, file:
>>>>>>>> !5, line: 49, size: 8, align: 8, elements: !43, identifier:
>>>>>>>> "_ZTSZ4funcvEUlvE_")
>>>>>>>> +!40 = !DISubprogram(name: "func", linkageName: "_Z4funcv", scope:
>>>>>>>> !5, file: !5, line: 47, type: !41, isLocal: false, isDefinition: true,
>>>>>>>> scopeLine: 47, flags: DIFlagPrototyped, isOptimized: false, function: i32
>>>>>>>> ()* @_Z4funcv, variables: !2)
>>>>>>>> +!41 = !DISubroutineType(types: !42)
>>>>>>>> +!42 = !{!8}
>>>>>>>> +!43 = !{!44}
>>>>>>>> +!44 = !DISubprogram(name: "operator()", scope:
>>>>>>>> !"_ZTSZ4funcvEUlvE_", file: !5, line: 49, type: !45, isLocal: false,
>>>>>>>> isDefinition: false, scopeLine: 49, flags: DIFlagPublic | DIFlagPrototyped,
>>>>>>>> isOptimized: false)
>>>>>>>> +!45 = !DISubroutineType(types: !46)
>>>>>>>> +!46 = !{!8, !47}
>>>>>>>> +!47 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !48,
>>>>>>>> size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
>>>>>>>> +!48 = !DIDerivedType(tag: DW_TAG_const_type, baseType:
>>>>>>>> !"_ZTSZ4funcvEUlvE_")
>>>>>>>> +!49 = !DICompositeType(tag: DW_TAG_structure_type, name:
>>>>>>>> "CInsideFunc", scope: !40, file: !5, line: 48, size: 32, align: 32,
>>>>>>>> elements: !50, identifier: "_ZTSZ4funcvE11CInsideFunc")
>>>>>>>> +!50 = !{!51}
>>>>>>>> +!51 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope:
>>>>>>>> !"_ZTSZ4funcvE11CInsideFunc", file: !5, line: 48, baseType: !8, size: 32,
>>>>>>>> align: 32)
>>>>>>>> +!52 = !{!53, !40, !54}
>>>>>>>> +!53 = !DISubprogram(name: "foo", linkageName: "_Z3foov", scope:
>>>>>>>> !1, file: !1, line: 3, type: !41, isLocal: false, isDefinition: true,
>>>>>>>> scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, function: i32
>>>>>>>> ()* @_Z3foov, variables: !2)
>>>>>>>> +!54 = !DISubprogram(name: "operator()", linkageName:
>>>>>>>> "_ZZ4funcvENKUlvE_clEv", scope: !"_ZTSZ4funcvEUlvE_", file: !5, line: 49,
>>>>>>>> type: !45, isLocal: false, isDefinition: true, scopeLine: 49, flags:
>>>>>>>> DIFlagPrototyped, isOptimized: false, function: i32 (%class.anon*)*
>>>>>>>> @_ZZ4funcvENKUlvE_clEv, declaration: !44, variables: !2)
>>>>>>>> +!55 = !{i32 2, !"Dwarf Version", i32 2}
>>>>>>>> +!56 = !{i32 2, !"Debug Info Version", i32 3}
>>>>>>>> +!57 = !{i32 1, !"PIC Level", i32 2}
>>>>>>>> +!58 = !{!"clang version 3.8.0 (trunk 242534)"}
>>>>>>>> +!59 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "s",
>>>>>>>> scope: !53, file: !1, line: 4, type: !28)
>>>>>>>> +!60 = !DIExpression()
>>>>>>>> +!61 = !DILocation(line: 4, column: 12, scope: !53)
>>>>>>>> +!62 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "nc",
>>>>>>>> scope: !53, file: !1, line: 5, type: !"_ZTSN1N1CE")
>>>>>>>> +!63 = !DILocation(line: 5, column: 7, scope: !53)
>>>>>>>> +!64 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "nnc",
>>>>>>>> scope: !53, file: !1, line: 6, type: !"_ZTSN1N1N1CE")
>>>>>>>> +!65 = !DILocation(line: 6, column: 10, scope: !53)
>>>>>>>> +!66 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "ac",
>>>>>>>> scope: !53, file: !1, line: 7, type: !67)
>>>>>>>> +!67 = !DICompositeType(tag: DW_TAG_class_type, name: "AnonC",
>>>>>>>> scope: !68, file: !5, line: 38, size: 8, align: 8, elements: !2)
>>>>>>>> +!68 = !DINamespace(scope: null, file: !5, line: 37)
>>>>>>>> +!69 = !DILocation(line: 7, column: 8, scope: !53)
>>>>>>>> +!70 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "u",
>>>>>>>> scope: !53, file: !1, line: 8, type: !"_ZTS1U")
>>>>>>>> +!71 = !DILocation(line: 8, column: 4, scope: !53)
>>>>>>>> +!72 = !DILocation(line: 10, column: 9, scope: !53)
>>>>>>>> +!73 = !DILocation(line: 10, column: 2, scope: !53)
>>>>>>>> +!74 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "functor",
>>>>>>>> scope: !40, file: !5, line: 49, type: !"_ZTSZ4funcvEUlvE_")
>>>>>>>> +!75 = !DILocation(line: 49, column: 7, scope: !40)
>>>>>>>> +!76 = !DILocation(line: 50, column: 9, scope: !40)
>>>>>>>> +!77 = !DILocation(line: 50, column: 2, scope: !40)
>>>>>>>> +!78 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this",
>>>>>>>> arg: 1, scope: !54, type: !79, flags: DIFlagArtificial |
>>>>>>>> DIFlagObjectPointer)
>>>>>>>> +!79 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !48,
>>>>>>>> size: 64, align: 64)
>>>>>>>> +!80 = !DILocation(line: 0, scope: !54)
>>>>>>>> +!81 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "dummy",
>>>>>>>> scope: !54, file: !5, line: 49, type: !"_ZTSZ4funcvE11CInsideFunc")
>>>>>>>> +!82 = !DILocation(line: 49, column: 36, scope: !54)
>>>>>>>> +!83 = !DILocation(line: 49, column: 56, scope: !54)
>>>>>>>> +!84 = !DILocation(line: 49, column: 43, scope: !54)
>>>>>>>>
>>>>>>>> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr2.cpp
>>>>>>>> URL:
>>>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr2.cpp?rev=242847&view=auto
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- llvm/trunk/test/tools/dsymutil/Inputs/odr2.cpp (added)
>>>>>>>> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr2.cpp Tue Jul 21
>>>>>>>> 17:41:43 2015
>>>>>>>> @@ -0,0 +1,7 @@
>>>>>>>> +#include "odr-types.h"
>>>>>>>> +
>>>>>>>> +int bar() {
>>>>>>>> +       S s;
>>>>>>>> +       s.incr();
>>>>>>>> +       return s.foo();
>>>>>>>> +}
>>>>>>>>
>>>>>>>> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr2.ll
>>>>>>>> URL:
>>>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr2.ll?rev=242847&view=auto
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- llvm/trunk/test/tools/dsymutil/Inputs/odr2.ll (added)
>>>>>>>> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr2.ll Tue Jul 21
>>>>>>>> 17:41:43 2015
>>>>>>>> @@ -0,0 +1,99 @@
>>>>>>>> +; Generated from odr2.cpp and odr-types.h by running:
>>>>>>>> +; clang -emit-llvm -g -S -std=c++11 odr2.cpp
>>>>>>>> +; ModuleID = 'odr2.cpp'
>>>>>>>> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>>>>>>>> +target triple = "x86_64-apple-macosx10.11.0"
>>>>>>>> +
>>>>>>>> +%struct.S = type { i32, %"struct.S::Nested" }
>>>>>>>> +%"struct.S::Nested" = type { double }
>>>>>>>> +
>>>>>>>> +; Function Attrs: ssp uwtable
>>>>>>>> +define i32 @_Z3barv() #0 {
>>>>>>>> +entry:
>>>>>>>> +  %this.addr.i = alloca %struct.S*, align 8
>>>>>>>> +  %s = alloca %struct.S, align 8
>>>>>>>> +  call void @llvm.dbg.declare(metadata %struct.S* %s, metadata
>>>>>>>> !34, metadata !35), !dbg !36
>>>>>>>> +  store %struct.S* %s, %struct.S** %this.addr.i, align 8, !dbg !37
>>>>>>>> +  %this1.i = load %struct.S*, %struct.S** %this.addr.i, !dbg !37
>>>>>>>> +  %I.i = getelementptr inbounds %struct.S, %struct.S* %this1.i,
>>>>>>>> i32 0, i32 0, !dbg !38
>>>>>>>> +  %0 = load i32, i32* %I.i, align 4, !dbg !40
>>>>>>>> +  %inc.i = add nsw i32 %0, 1, !dbg !40
>>>>>>>> +  store i32 %inc.i, i32* %I.i, align 4, !dbg !40
>>>>>>>> +  %call = call i32 @_ZN1S3fooEv(%struct.S* %s), !dbg !41
>>>>>>>> +  call void @llvm.dbg.declare(metadata %struct.S** %this.addr.i,
>>>>>>>> metadata !42, metadata !35), !dbg !44
>>>>>>>> +  ret i32 %call, !dbg !45
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +; Function Attrs: nounwind readnone
>>>>>>>> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
>>>>>>>> +
>>>>>>>> +; Function Attrs: nounwind ssp uwtable
>>>>>>>> +define linkonce_odr i32 @_ZN1S3fooEv(%struct.S* %this) #2 align 2 {
>>>>>>>> +entry:
>>>>>>>> +  %this.addr = alloca %struct.S*, align 8
>>>>>>>> +  store %struct.S* %this, %struct.S** %this.addr, align 8
>>>>>>>> +  call void @llvm.dbg.declare(metadata %struct.S** %this.addr,
>>>>>>>> metadata !46, metadata !35), !dbg !47
>>>>>>>> +  %this1 = load %struct.S*, %struct.S** %this.addr
>>>>>>>> +  %I = getelementptr inbounds %struct.S, %struct.S* %this1, i32 0,
>>>>>>>> i32 0, !dbg !48
>>>>>>>> +  %0 = load i32, i32* %I, align 4, !dbg !48
>>>>>>>> +  ret i32 %0, !dbg !49
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +attributes #0 = { ssp uwtable "disable-tail-calls"="false"
>>>>>>>> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
>>>>>>>> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
>>>>>>>> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
>>>>>>>> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
>>>>>>>> "unsafe-fp-math"="false" "use-soft-float"="false" }
>>>>>>>> +attributes #1 = { nounwind readnone }
>>>>>>>> +attributes #2 = { nounwind ssp uwtable
>>>>>>>> "disable-tail-calls"="false" "less-precise-fpmad"="false"
>>>>>>>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"
>>>>>>>> "no-infs-fp-math"="false" "no-nans-fp-math"="false"
>>>>>>>> "stack-protector-buffer-size"="8" "target-cpu"="core2"
>>>>>>>> "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false"
>>>>>>>> "use-soft-float"="false" }
>>>>>>>> +
>>>>>>>> +!llvm.dbg.cu = !{!0}
>>>>>>>> +!llvm.module.flags = !{!30, !31, !32}
>>>>>>>> +!llvm.ident = !{!33}
>>>>>>>> +
>>>>>>>> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file:
>>>>>>>> !1, producer: "clang version 3.8.0 (trunk 242534)", isOptimized: false,
>>>>>>>> runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !3,
>>>>>>>> subprograms: !24)
>>>>>>>> +!1 = !DIFile(filename: "odr2.cpp", directory: "/Inputs")
>>>>>>>> +!2 = !{}
>>>>>>>> +!3 = !{!4, !20}
>>>>>>>> +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", file:
>>>>>>>> !5, line: 1, size: 128, align: 64, elements: !6, identifier: "_ZTS1S")
>>>>>>>> +!5 = !DIFile(filename: "./odr-types.h", directory: "/Inputs")
>>>>>>>> +!6 = !{!7, !9, !10, !14, !17}
>>>>>>>> +!7 = !DIDerivedType(tag: DW_TAG_member, name: "I", scope:
>>>>>>>> !"_ZTS1S", file: !5, line: 2, baseType: !8, size: 32, align: 32)
>>>>>>>> +!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding:
>>>>>>>> DW_ATE_signed)
>>>>>>>> +!9 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
>>>>>>>> !"_ZTS1S", file: !5, line: 15, baseType: !"_ZTSN1S6NestedE", size: 64,
>>>>>>>> align: 64, offset: 64)
>>>>>>>> +!10 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEv",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 4, type: !11, isLocal: false,
>>>>>>>> isDefinition: false, scopeLine: 4, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false)
>>>>>>>> +!11 = !DISubroutineType(types: !12)
>>>>>>>> +!12 = !{null, !13}
>>>>>>>> +!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType:
>>>>>>>> !"_ZTS1S", size: 64, align: 64, flags: DIFlagArtificial |
>>>>>>>> DIFlagObjectPointer)
>>>>>>>> +!14 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEi",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 5, type: !15, isLocal: false,
>>>>>>>> isDefinition: false, scopeLine: 5, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false)
>>>>>>>> +!15 = !DISubroutineType(types: !16)
>>>>>>>> +!16 = !{null, !13, !8}
>>>>>>>> +!17 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false,
>>>>>>>> isDefinition: false, scopeLine: 18, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false)
>>>>>>>> +!18 = !DISubroutineType(types: !19)
>>>>>>>> +!19 = !{!8, !13}
>>>>>>>> +!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "Nested",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 9, size: 64, align: 64, elements: !21,
>>>>>>>> identifier: "_ZTSN1S6NestedE")
>>>>>>>> +!21 = !{!22}
>>>>>>>> +!22 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
>>>>>>>> !"_ZTSN1S6NestedE", file: !5, line: 10, baseType: !23, size: 64, align: 64)
>>>>>>>> +!23 = !DIBasicType(name: "double", size: 64, align: 64, encoding:
>>>>>>>> DW_ATE_float)
>>>>>>>> +!24 = !{!25, !28, !29}
>>>>>>>> +!25 = !DISubprogram(name: "bar", linkageName: "_Z3barv", scope:
>>>>>>>> !1, file: !1, line: 3, type: !26, isLocal: false, isDefinition: true,
>>>>>>>> scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, function: i32
>>>>>>>> ()* @_Z3barv, variables: !2)
>>>>>>>> +!26 = !DISubroutineType(types: !27)
>>>>>>>> +!27 = !{!8}
>>>>>>>> +!28 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEv",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 4, type: !11, isLocal: false,
>>>>>>>> isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false, declaration: !10, variables: !2)
>>>>>>>> +!29 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false,
>>>>>>>> isDefinition: true, scopeLine: 18, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false, function: i32 (%struct.S*)* @_ZN1S3fooEv, declaration: !17,
>>>>>>>> variables: !2)
>>>>>>>> +!30 = !{i32 2, !"Dwarf Version", i32 2}
>>>>>>>> +!31 = !{i32 2, !"Debug Info Version", i32 3}
>>>>>>>> +!32 = !{i32 1, !"PIC Level", i32 2}
>>>>>>>> +!33 = !{!"clang version 3.8.0 (trunk 242534)"}
>>>>>>>> +!34 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "s",
>>>>>>>> scope: !25, file: !1, line: 4, type: !"_ZTS1S")
>>>>>>>> +!35 = !DIExpression()
>>>>>>>> +!36 = !DILocation(line: 4, column: 4, scope: !25)
>>>>>>>> +!37 = !DILocation(line: 5, column: 2, scope: !25)
>>>>>>>> +!38 = !DILocation(line: 4, column: 47, scope: !28, inlinedAt: !39)
>>>>>>>> +!39 = distinct !DILocation(line: 5, column: 2, scope: !25)
>>>>>>>> +!40 = !DILocation(line: 4, column: 48, scope: !28, inlinedAt: !39)
>>>>>>>> +!41 = !DILocation(line: 6, column: 9, scope: !25)
>>>>>>>> +!42 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this",
>>>>>>>> arg: 1, scope: !28, type: !43, flags: DIFlagArtificial |
>>>>>>>> DIFlagObjectPointer)
>>>>>>>> +!43 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType:
>>>>>>>> !"_ZTS1S", size: 64, align: 64)
>>>>>>>> +!44 = !DILocation(line: 0, scope: !28, inlinedAt: !39)
>>>>>>>> +!45 = !DILocation(line: 6, column: 2, scope: !25)
>>>>>>>> +!46 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this",
>>>>>>>> arg: 1, scope: !29, type: !43, flags: DIFlagArtificial |
>>>>>>>> DIFlagObjectPointer)
>>>>>>>> +!47 = !DILocation(line: 0, scope: !29)
>>>>>>>> +!48 = !DILocation(line: 18, column: 21, scope: !29)
>>>>>>>> +!49 = !DILocation(line: 18, column: 14, scope: !29)
>>>>>>>>
>>>>>>>> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr3.cpp
>>>>>>>> URL:
>>>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr3.cpp?rev=242847&view=auto
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- llvm/trunk/test/tools/dsymutil/Inputs/odr3.cpp (added)
>>>>>>>> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr3.cpp Tue Jul 21
>>>>>>>> 17:41:43 2015
>>>>>>>> @@ -0,0 +1,7 @@
>>>>>>>> +#include "odr-types.h"
>>>>>>>> +
>>>>>>>> +int bar() {
>>>>>>>> +       S s;
>>>>>>>> +       s.incr(42);
>>>>>>>> +       return s.foo();
>>>>>>>> +}
>>>>>>>>
>>>>>>>> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr3.ll
>>>>>>>> URL:
>>>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr3.ll?rev=242847&view=auto
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- llvm/trunk/test/tools/dsymutil/Inputs/odr3.ll (added)
>>>>>>>> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr3.ll Tue Jul 21
>>>>>>>> 17:41:43 2015
>>>>>>>> @@ -0,0 +1,106 @@
>>>>>>>> +; Generated from odr3.cpp and odr-types.h by running:
>>>>>>>> +; clang -emit-llvm -g -S -std=c++11 odr3.cpp
>>>>>>>> +; ModuleID = 'odr3.cpp'
>>>>>>>> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>>>>>>>> +target triple = "x86_64-apple-macosx10.11.0"
>>>>>>>> +
>>>>>>>> +%struct.S = type { i32, %"struct.S::Nested" }
>>>>>>>> +%"struct.S::Nested" = type { double }
>>>>>>>> +
>>>>>>>> +; Function Attrs: ssp uwtable
>>>>>>>> +define i32 @_Z3barv() #0 {
>>>>>>>> +entry:
>>>>>>>> +  %this.addr.i = alloca %struct.S*, align 8
>>>>>>>> +  %Add.addr.i = alloca i32, align 4
>>>>>>>> +  %s = alloca %struct.S, align 8
>>>>>>>> +  call void @llvm.dbg.declare(metadata %struct.S* %s, metadata
>>>>>>>> !34, metadata !35), !dbg !36
>>>>>>>> +  store %struct.S* %s, %struct.S** %this.addr.i, align 8, !dbg !37
>>>>>>>> +  store i32 42, i32* %Add.addr.i, align 4, !dbg !37
>>>>>>>> +  %this1.i = load %struct.S*, %struct.S** %this.addr.i, !dbg !37
>>>>>>>> +  %0 = load i32, i32* %Add.addr.i, align 4, !dbg !38
>>>>>>>> +  %I.i = getelementptr inbounds %struct.S, %struct.S* %this1.i,
>>>>>>>> i32 0, i32 0, !dbg !40
>>>>>>>> +  %1 = load i32, i32* %I.i, align 4, !dbg !41
>>>>>>>> +  %add.i = add nsw i32 %1, %0, !dbg !41
>>>>>>>> +  store i32 %add.i, i32* %I.i, align 4, !dbg !41
>>>>>>>> +  %call = call i32 @_ZN1S3fooEv(%struct.S* %s), !dbg !42
>>>>>>>> +  call void @llvm.dbg.declare(metadata %struct.S** %this.addr.i,
>>>>>>>> metadata !43, metadata !35), !dbg !45
>>>>>>>> +  call void @llvm.dbg.declare(metadata i32* %Add.addr.i, metadata
>>>>>>>> !46, metadata !35), !dbg !47
>>>>>>>> +  ret i32 %call, !dbg !48
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +; Function Attrs: nounwind readnone
>>>>>>>> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
>>>>>>>> +
>>>>>>>> +; Function Attrs: nounwind ssp uwtable
>>>>>>>> +define linkonce_odr i32 @_ZN1S3fooEv(%struct.S* %this) #2 align 2 {
>>>>>>>> +entry:
>>>>>>>> +  %this.addr = alloca %struct.S*, align 8
>>>>>>>> +  store %struct.S* %this, %struct.S** %this.addr, align 8
>>>>>>>> +  call void @llvm.dbg.declare(metadata %struct.S** %this.addr,
>>>>>>>> metadata !49, metadata !35), !dbg !50
>>>>>>>> +  %this1 = load %struct.S*, %struct.S** %this.addr
>>>>>>>> +  %I = getelementptr inbounds %struct.S, %struct.S* %this1, i32 0,
>>>>>>>> i32 0, !dbg !51
>>>>>>>> +  %0 = load i32, i32* %I, align 4, !dbg !51
>>>>>>>> +  ret i32 %0, !dbg !52
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +attributes #0 = { ssp uwtable "disable-tail-calls"="false"
>>>>>>>> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
>>>>>>>> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
>>>>>>>> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
>>>>>>>> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
>>>>>>>> "unsafe-fp-math"="false" "use-soft-float"="false" }
>>>>>>>> +attributes #1 = { nounwind readnone }
>>>>>>>> +attributes #2 = { nounwind ssp uwtable
>>>>>>>> "disable-tail-calls"="false" "less-precise-fpmad"="false"
>>>>>>>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"
>>>>>>>> "no-infs-fp-math"="false" "no-nans-fp-math"="false"
>>>>>>>> "stack-protector-buffer-size"="8" "target-cpu"="core2"
>>>>>>>> "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false"
>>>>>>>> "use-soft-float"="false" }
>>>>>>>> +
>>>>>>>> +!llvm.dbg.cu = !{!0}
>>>>>>>> +!llvm.module.flags = !{!30, !31, !32}
>>>>>>>> +!llvm.ident = !{!33}
>>>>>>>> +
>>>>>>>> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file:
>>>>>>>> !1, producer: "clang version 3.8.0 (trunk 242534)", isOptimized: false,
>>>>>>>> runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !3,
>>>>>>>> subprograms: !24)
>>>>>>>> +!1 = !DIFile(filename: "odr3.cpp", directory: "/Inputs")
>>>>>>>> +!2 = !{}
>>>>>>>> +!3 = !{!4, !20}
>>>>>>>> +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", file:
>>>>>>>> !5, line: 1, size: 128, align: 64, elements: !6, identifier: "_ZTS1S")
>>>>>>>> +!5 = !DIFile(filename: "./odr-types.h", directory: "/Inputs")
>>>>>>>> +!6 = !{!7, !9, !10, !14, !17}
>>>>>>>> +!7 = !DIDerivedType(tag: DW_TAG_member, name: "I", scope:
>>>>>>>> !"_ZTS1S", file: !5, line: 2, baseType: !8, size: 32, align: 32)
>>>>>>>> +!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding:
>>>>>>>> DW_ATE_signed)
>>>>>>>> +!9 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
>>>>>>>> !"_ZTS1S", file: !5, line: 15, baseType: !"_ZTSN1S6NestedE", size: 64,
>>>>>>>> align: 64, offset: 64)
>>>>>>>> +!10 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEv",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 4, type: !11, isLocal: false,
>>>>>>>> isDefinition: false, scopeLine: 4, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false)
>>>>>>>> +!11 = !DISubroutineType(types: !12)
>>>>>>>> +!12 = !{null, !13}
>>>>>>>> +!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType:
>>>>>>>> !"_ZTS1S", size: 64, align: 64, flags: DIFlagArtificial |
>>>>>>>> DIFlagObjectPointer)
>>>>>>>> +!14 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEi",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 5, type: !15, isLocal: false,
>>>>>>>> isDefinition: false, scopeLine: 5, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false)
>>>>>>>> +!15 = !DISubroutineType(types: !16)
>>>>>>>> +!16 = !{null, !13, !8}
>>>>>>>> +!17 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false,
>>>>>>>> isDefinition: false, scopeLine: 18, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false)
>>>>>>>> +!18 = !DISubroutineType(types: !19)
>>>>>>>> +!19 = !{!8, !13}
>>>>>>>> +!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "Nested",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 9, size: 64, align: 64, elements: !21,
>>>>>>>> identifier: "_ZTSN1S6NestedE")
>>>>>>>> +!21 = !{!22}
>>>>>>>> +!22 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
>>>>>>>> !"_ZTSN1S6NestedE", file: !5, line: 10, baseType: !23, size: 64, align: 64)
>>>>>>>> +!23 = !DIBasicType(name: "double", size: 64, align: 64, encoding:
>>>>>>>> DW_ATE_float)
>>>>>>>> +!24 = !{!25, !28, !29}
>>>>>>>> +!25 = !DISubprogram(name: "bar", linkageName: "_Z3barv", scope:
>>>>>>>> !1, file: !1, line: 3, type: !26, isLocal: false, isDefinition: true,
>>>>>>>> scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, function: i32
>>>>>>>> ()* @_Z3barv, variables: !2)
>>>>>>>> +!26 = !DISubroutineType(types: !27)
>>>>>>>> +!27 = !{!8}
>>>>>>>> +!28 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEi",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 5, type: !15, isLocal: false,
>>>>>>>> isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false, declaration: !14, variables: !2)
>>>>>>>> +!29 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv",
>>>>>>>> scope: !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false,
>>>>>>>> isDefinition: true, scopeLine: 18, flags: DIFlagPrototyped, isOptimized:
>>>>>>>> false, function: i32 (%struct.S*)* @_ZN1S3fooEv, declaration: !17,
>>>>>>>> variables: !2)
>>>>>>>> +!30 = !{i32 2, !"Dwarf Version", i32 2}
>>>>>>>> +!31 = !{i32 2, !"Debug Info Version", i32 3}
>>>>>>>> +!32 = !{i32 1, !"PIC Level", i32 2}
>>>>>>>> +!33 = !{!"clang version 3.8.0 (trunk 242534)"}
>>>>>>>> +!34 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "s",
>>>>>>>> scope: !25, file: !1, line: 4, type: !"_ZTS1S")
>>>>>>>> +!35 = !DIExpression()
>>>>>>>> +!36 = !DILocation(line: 4, column: 4, scope: !25)
>>>>>>>> +!37 = !DILocation(line: 5, column: 2, scope: !25)
>>>>>>>> +!38 = !DILocation(line: 5, column: 59, scope: !28, inlinedAt: !39)
>>>>>>>> +!39 = distinct !DILocation(line: 5, column: 2, scope: !25)
>>>>>>>> +!40 = !DILocation(line: 5, column: 54, scope: !28, inlinedAt: !39)
>>>>>>>> +!41 = !DILocation(line: 5, column: 56, scope: !28, inlinedAt: !39)
>>>>>>>> +!42 = !DILocation(line: 6, column: 9, scope: !25)
>>>>>>>> +!43 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this",
>>>>>>>> arg: 1, scope: !28, type: !44, flags: DIFlagArtificial |
>>>>>>>> DIFlagObjectPointer)
>>>>>>>> +!44 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType:
>>>>>>>> !"_ZTS1S", size: 64, align: 64)
>>>>>>>> +!45 = !DILocation(line: 0, scope: !28, inlinedAt: !39)
>>>>>>>> +!46 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "Add", arg:
>>>>>>>> 2, scope: !28, file: !5, line: 5, type: !8)
>>>>>>>> +!47 = !DILocation(line: 5, column: 16, scope: !28, inlinedAt: !39)
>>>>>>>> +!48 = !DILocation(line: 6, column: 2, scope: !25)
>>>>>>>> +!49 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this",
>>>>>>>> arg: 1, scope: !29, type: !44, flags: DIFlagArtificial |
>>>>>>>> DIFlagObjectPointer)
>>>>>>>> +!50 = !DILocation(line: 0, scope: !29)
>>>>>>>> +!51 = !DILocation(line: 18, column: 21, scope: !29)
>>>>>>>> +!52 = !DILocation(line: 18, column: 14, scope: !29)
>>>>>>>>
>>>>>>>> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr4.cpp
>>>>>>>> URL:
>>>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr4.cpp?rev=242847&view=auto
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- llvm/trunk/test/tools/dsymutil/Inputs/odr4.cpp (added)
>>>>>>>> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr4.cpp Tue Jul 21
>>>>>>>> 17:41:43 2015
>>>>>>>> @@ -0,0 +1,8 @@
>>>>>>>> +namespace {
>>>>>>>> +       class AnonC {
>>>>>>>> +       };
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +void baz() {
>>>>>>>> +       AnonC ac;
>>>>>>>> +}
>>>>>>>>
>>>>>>>> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr4.ll
>>>>>>>> URL:
>>>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr4.ll?rev=242847&view=auto
>>>>>>>>
>>>>>>>> ==============================================================================
>>>>>>>> --- llvm/trunk/test/tools/dsymutil/Inputs/odr4.ll (added)
>>>>>>>> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr4.ll Tue Jul 21
>>>>>>>> 17:41:43 2015
>>>>>>>> @@ -0,0 +1,43 @@
>>>>>>>> +; Generated from odr4.cpp and odr-types.h by running:
>>>>>>>> +; clang -emit-llvm -g -S -std=c++11 odr4.cpp
>>>>>>>> +; ModuleID = 'odr4.cpp'
>>>>>>>> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>>>>>>>> +target triple = "x86_64-apple-macosx10.11.0"
>>>>>>>> +
>>>>>>>> +%"class.(anonymous namespace)::AnonC" = type { i8 }
>>>>>>>> +
>>>>>>>> +; Function Attrs: nounwind ssp uwtable
>>>>>>>> +define void @_Z3bazv() #0 {
>>>>>>>> +entry:
>>>>>>>> +  %ac = alloca %"class.(anonymous namespace)::AnonC", align 1
>>>>>>>> +  call void @llvm.dbg.declare(metadata %"class.(anonymous
>>>>>>>> namespace)::AnonC"* %ac, metadata !11, metadata !14), !dbg !15
>>>>>>>> +  ret void, !dbg !16
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +; Function Attrs: nounwind readnone
>>>>>>>> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
>>>>>>>> +
>>>>>>>> +attributes #0 = { nounwind ssp uwtable
>>>>>>>> "disable-tail-calls"="false" "less-precise-fpmad"="false"
>>>>>>>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"
>>>>>>>> "no-infs-fp-math"="false" "no-nans-fp-math"="false"
>>>>>>>> "stack-protector-buffer-size"="8" "target-cpu"="core2"
>>>>>>>> "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false"
>>>>>>>> "use-soft-float"="false" }
>>>>>>>> +attribut
>>>>>>>
>>>>>>>
>> ...
>>
>> [Message clipped]
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150807/b7abe53e/attachment-0001.html>


More information about the llvm-commits mailing list