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

Frédéric Riss via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 7 11:24:28 PDT 2015


[with the right list this time]

> On Aug 7, 2015, at 11:02 AM, David Blaikie <dblaikie at gmail.com <mailto: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?)

Yes. The current logic will unique types in anonymous namespaces if the file/line matches. I want to test the case when they don’t match. I think this is wrong (and there is a FIXME in the code). I can build a (convoluted) test using preprocessor macros that breaks with the current logic, but for the sake of compatibility with dsymutil-classic for now it works this way.  

> 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)

I know that, but I usually write my CHECK lines and then insert the generic CHECK-NOT ones in one go. I’ll go through it and remove the useless conditions.

> 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?))

/goes back to the test to check

In the test as written, they do not test much. Their intent in the original test was to verify that dsymutil wouldn’t confuse foo() and foo(int). I’ll mark them always_inline add tests to check that the DW_TAG_inlined_subroutine refer to the correct one. 

> Misspelling of implicit (implicit)

thanks

> 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)

For these tests where the symbols don’t matter, I’d be more inclined to work on a mode where we don’t need a debug map file at all. However that’s a feature that would be useful only for that test and it’s not actually totally trivial to implement. I could make it work by playing with the paths in the tests, but I’m not sure it’s worth it. The current setup is pretty clear even if a bit verbose.

Fred

> 
> On Mon, Aug 3, 2015 at 3:39 PM, Frédéric Riss <friss at apple.com <mailto: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 <mailto:dblaikie at gmail.com>> wrote:
>> 
>> 
>> 
>> On Wed, Jul 29, 2015 at 3:58 PM, Frédéric Riss <friss at apple.com <mailto:friss at apple.com>> wrote:
>> 
>>> On Jul 29, 2015, at 3:35 PM, David Blaikie <dblaikie at gmail.com <mailto:dblaikie at gmail.com>> wrote:
>>> 
>>> 
>>> 
>>> On Wed, Jul 29, 2015 at 3:09 PM, Frédéric Riss <friss at apple.com <mailto: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 <mailto:dblaikie at gmail.com>> wrote:
>>>> 
>>>> 
>>>> 
>>>> On Mon, Jul 27, 2015 at 2:25 PM, Frédéric Riss <friss at apple.com <mailto:friss at apple.com>> wrote:
>>>> 
>>>>> On Jul 27, 2015, at 1:03 PM, David Blaikie <dblaikie at gmail.com <mailto:dblaikie at gmail.com>> wrote:
>>>>> 
>>>>> 
>>>>> 
>>>>> On Mon, Jul 27, 2015 at 12:33 PM, Frédéric Riss <friss at apple.com <mailto: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 <mailto:dblaikie at gmail.com>> wrote:
>>>>>> On Tue, Jul 21, 2015 at 5:02 PM, Frédéric Riss <friss at apple.com <mailto:friss at apple.com>> wrote:
>>>>>> 
>>>>>>> On Jul 21, 2015, at 4:05 PM, David Blaikie <dblaikie at gmail.com <mailto:dblaikie at gmail.com>> wrote:
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> On Tue, Jul 21, 2015 at 3:41 PM, Frederic Riss <friss at apple.com <mailto: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 <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 <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 <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 <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 <http://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 <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 <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 <http://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 <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 <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 <http://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 <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 <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/4a4cbd43/attachment-0001.html>


More information about the llvm-commits mailing list