<div dir="rtl"><div dir="ltr">In MSVC raw_name does return a unique name:</div><div dir="ltr"><br></div><div dir="ltr"><div dir="ltr"><font face="courier new, monospace">tu1().raw_name: .?AUFoo@?A0x08cd7644@@</font></div><div dir="ltr">

<font face="courier new, monospace">tu2().raw_name: .?AUFoo@?A0x8e5904ea@@</font></div><div dir="ltr"><br></div><div>In gcc these are the same. </div><div><br></div><div>libsupc++ code compares pointer to type, pointers to the name or the name itself depending upon defines. It says:</div>

<div><br></div><div><div>// Determine whether typeinfo names for the same type are merged (in which</div><div>// case comparison can just compare pointers) or not (in which case strings</div><div>// must be compared), and whether comparison is to be implemented inline or</div>

<div>// not.  We used to do inline pointer comparison by default if weak symbols</div><div>// are available, but even with weak symbols sometimes names are not merged</div><div>// when objects are loaded with RTLD_LOCAL, so now we always use strcmp by</div>

<div>// default.  For ABI compatibility, we do the strcmp inline if weak symbols</div><div>// are available, and out-of-line if not.  Out-of-line pointer comparison</div></div><div>...</div><div>// Even with the new abi, on systems that support dlopen</div>

<div><div>// we can run into cases where type_info names aren't merged,</div><div>// so we still need to do string comparison.</div></div><div><br></div><div>The problem goes beyond anonymous namespace. Without them, the catch handler will catch based on  name only, leading to interesting C-like bugs.</div>

<div><br></div><div> x1.cpp:</div><div><br></div><div><div><font face="courier new, monospace">#include <typeinfo></font></div><div><font face="courier new, monospace">struct Foo { int a; int b; Foo(int a_, int b_) : a(a_), b(b_) {} };</font></div>

<div><font face="courier new, monospace">extern "C" void printf(const char *, ...);</font></div><div><font face="courier new, monospace">const std::type_info &tu1() { return typeid(Foo); }</font></div><div>
<font face="courier new, monospace">__declspec(dllexport) void x1() {</font></div>
<div><font face="courier new, monospace">  printf("tu1().name: %s,%x\n", tu1().name(), (unsigned)tu1().name());</font></div><div><font face="courier new, monospace">  throw Foo(12,34);</font></div><div><font face="courier new, monospace">}</font></div>

</div><div><br></div><div>x2.cpp:</div><div><br></div><div><div><font face="courier new, monospace">#include <typeinfo></font></div><div><font face="courier new, monospace">struct Foo { double x; };</font></div><div>

<font face="courier new, monospace">extern void x1();</font></div><div><font face="courier new, monospace">extern "C" void printf(const char *, ...);</font></div><div><font face="courier new, monospace">const std::type_info &tu2() { return typeid(Foo); }</font></div>

<div><font face="courier new, monospace">int main() {</font></div><div><font face="courier new, monospace">  printf("tu2().name: %s,%x\n", tu2().name(), (unsigned)tu2().name());</font></div><div><font face="courier new, monospace">  try { x1(); }  </font></div>

<div><font face="courier new, monospace">  catch (Foo F) { printf("Caught Foo x=%g\n", F.x); }</font></div><div><font face="courier new, monospace">  return 0;</font></div><div><font face="courier new, monospace">}</font></div>

</div><div><br></div><div>with either gcc 4.8.1 or Visual C++ 2012 gets bad result:</div><div><div><br></div><div><font face="courier new, monospace">gcc -shared x1.cpp -o x1.dll -lstdc++ && gcc x2.cpp x1.dll -o x1.exe -lstdc++ && ./x1</font></div>

<div><font face="courier new, monospace"><div>tu2().name: 3Foo,4088b8</div><div>tu1().name: 3Foo,69404188</div><div>Caught Foo x=7.21479e-313</div></font></div><div><br></div><div><font face="courier new, monospace">cl -EHsc  -LD x1.cpp -Fex1.dll && cl -EHsc x2.cpp x1.lib && x2</font></div>

</div><div><div><font face="courier new, monospace">tu2().name: struct Foo,5be448</font></div><div><font face="courier new, monospace">tu1().name: struct Foo,5be460</font></div><div><font face="courier new, monospace">Caught Foo x=7.21479e-313</font></div>

</div><div><br></div><div>(without a namespace, VC raw_name() are identical)</div><div><br></div><div>The problem is nothing encodes the internal structure of Foo. Maybe the typeid could be a 64-bit hash based on everything relevant: namespace, name, members and then it would be the same even for different TU and could be used in all situations.</div>

<div><br></div><div>Yaron</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></div></div><div class="gmail_extra"><div dir="ltr"><br><br><div class="gmail_quote">2013/11/23 Reid Kleckner <span dir="ltr"><<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>></span><br>

<blockquote class="gmail_quote" style="margin:0 .8ex;border-left:1px #ccc solid;border-right:1px #ccc solid;padding-left:1ex;padding-right:1ex"><div class="gmail_extra"><div class="gmail_quote"><div class="im">On Fri, Nov 22, 2013 at 3:08 PM, Yaron Keren <span dir="ltr"><<a href="mailto:yaron.keren@gmail.com" target="_blank">yaron.keren@gmail.com</a>></span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="rtl"><div dir="ltr">MSVC is confused by the same-named source file!</div>


<div dir="ltr">If the code is split into  t1.cpp:<br></div></div></blockquote><div><br></div></div><div>Oh, right, I discovered that yesterday.  It's really annoying, considering that my standard testing methodology is to use the same file compiled twice.  :(</div>

<div class="im">
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="rtl"><div dir="ltr"><div>However, your point IS valid, since when the actual names are printed (names which will be used in the strcmp):</div>


<div><br></div><div><div><font face="courier new, monospace">  printf("tu1().name: %s\n", tu1().name());</font></div>

<div><font face="courier new, monospace">  printf("tu2().name: %s\n", tu2().name());</font></div></div><div><br></div><div>with MSVC we get</div><div><br></div><div><div><font face="courier new, monospace">tu1() == tu2(): 0</font></div>




<div><font face="courier new, monospace">tu1().name: struct `anonymous namespace'::Foo</font></div><div><font face="courier new, monospace">tu2().name: struct `anonymous namespace'::Foo</font></div></div><div><br>




</div><div>and with gcc:</div><div><br></div><div><div><font face="courier new, monospace">tu1() == tu2(): 0</font></div><div><font face="courier new, monospace">tu1().name: *N12_GLOBAL__N_13FooE</font></div><div><font face="courier new, monospace">tu2().name: *N12_GLOBAL__N_13FooE</font></div>




</div><div><br></div><div>So when comparing type ids only, we'll miss exceptions from DLLs, while if we compare type names as well we may catch a same-named class coming from the same namespace even it's actually something different.</div>




<div><br></div><div>Given only these two options (maybe there is a better solution?), I'd still go with the first, since many C++ DLL libraries throw exceptions which *must* be caught, else the library is not usable. This is a showstopper.</div>




<div><br></div><div>OTOH, same-named classes - in the same namespace - in different TU are probably uncommon and throwing them around where they might be confused is probably even less common.</div></div></div></blockquote>


<div><br></div></div><div>MSDN says MSVC lets you get at the mangled/decorated name with .raw_name(), and this should be good enough, barring people like me recompiling the same source file with different macros.  :)</div>

<div>
<br></div><div>I don't see how to fix this for gcc, though, if they don't surface a unique mangled name for types in anonymous namespaces.</div></div></div></blockquote></div></div></div>