<html>
    <head>
      <base href="http://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - ModuleLinker "chooses" the wrong DISubprogram when linkonce_odr is replaced by weak_odr"
   href="http://llvm.org/bugs/show_bug.cgi?id=21910">21910</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>ModuleLinker "chooses" the wrong DISubprogram when linkonce_odr is replaced by weak_odr
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Linker
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>dexonsmith@apple.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=13537" name="attach_13537" title="repro.tar.gz: demonstrate mismatched "first subprogram" vs. "chosen subprogram"">attachment 13537</a> <a href="attachment.cgi?id=13537&action=edit" title="repro.tar.gz: demonstrate mismatched "first subprogram" vs. "chosen subprogram"">[details]</a></span>
repro.tar.gz: demonstrate mismatched "first subprogram" vs. "chosen subprogram"

When a `linkonce_odr` function gets replaced by a `weak_odr` function, the new
function body's `!dbg` references point at a potentially new DW_TAG_subprogram
in a new DW_TAG_compile_unit.

Some algorithms assume the first `DW_TAG_subprogram` that points at an
`llvm::Function*` is the canonical one, where the first is obtained by walking
compile units in order, and within those, walking their subprograms.  (Maybe it
is?)

Although DW_TAG_subprograms usually de-dup, you can trivially create a
discrepancy by having the `weak_odr` come from a compile_unit that was compiled
in a different directory than the `linkonce_odr`, and linking in the `weak_odr`
version second.

I think (?) the right result would be for the destination module to only
contain one copy of the subprogram, and for it to be the one from the compile
unit that had `weak_odr` linkage.  It's not clear whether that's practical,
though.

Attaching repro.tar.gz, which demonstrates how to create the discrepancy:

$ tar xzf repro.tar.gz
$ cd repro/
$ for f in *.h */*.cpp; do echo "// $f"; cat $f; done
// t.h
template <class T> struct Class {
  int foo() { return 0; }
};
// d1/t1.cpp
#include "t.h"
int foo() { return Class<int>().foo(); }
// d2/t2.cpp
#include "t.h"
template struct Class<int>;
$ make
cd d1 && clang -I.. -c -emit-llvm -gline-tables-only -o t1.bc t1.cpp
cd d2 && clang -I.. -c -emit-llvm -gline-tables-only -o t2.bc t2.cpp
llvm-link -S -o linked.ll d1/t1.bc d2/t2.bc
llvm-link -o linked.bc d1/t1.bc d2/t2.bc
$ grep -e '!dbg !20' linked.ll -B4
define weak_odr i32 @_ZN5ClassIiE3fooEv(%struct.Class* %this) #1 align 2 {
  %1 = alloca %struct.Class*, align 8
  store %struct.Class* %this, %struct.Class** %1, align 8
  %2 = load %struct.Class** %1
  ret i32 0, !dbg !20
$ grep -e '^!20 ' linked.ll 
!20 = metadata !{i32 2, i32 0, metadata !13, null}
$ grep -e '@_ZN5ClassIiE3fooEv, ' linked.ll 
!7 = metadata !{i32 786478, metadata !8, metadata !9, metadata !"foo", metadata
!"foo", metadata !"", i32 2, metadata !6, i1 false, i1 true, i32 0, i32 0,
null, i32 256, i1 false, i32 (%struct.Class*)* @_ZN5ClassIiE3fooEv, null, null,
metadata !2, i32 2}
!13 = metadata !{i32 786478, metadata !14, metadata !15, metadata !"foo",
metadata !"foo", metadata !"", i32 2, metadata !6, i1 false, i1 true, i32 0,
i32 0, null, i32 256, i1 false, i32 (%struct.Class*)* @_ZN5ClassIiE3fooEv,
null, null, metadata !2, i32 2}</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>