<div dir="ltr">Hi Hans,<div><br></div><div>I fixed the problem that caused Nico to revert this. I would like to re-land this in 3.8.</div><div>This depends on libc++ commit r258217 also landing in 3.8.</div><div><br></div><div>@Marshall can you OK this?</div><div><br></div><div>/Eric</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 19, 2016 at 4:42 PM, Eric Fiselier via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ericwf<br>
Date: Tue Jan 19 17:42:10 2016<br>
New Revision: 258249<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=258249&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=258249&view=rev</a><br>
Log:<br>
Recommit r256322: Fix PR25898 - Check for incomplete pointers types in can_catch(...)<br>
<br>
This patch re-commits r256322 and r256323. They were reverted due to a OS X<br>
test failure. The test failure has been fixed by libc++ commit r258217.<br>
<br>
This patch also adds some additional tests.<br>
<br>
Added:<br>
    libcxxabi/trunk/test/incomplete_type.sh.cpp<br>
Modified:<br>
    libcxxabi/trunk/src/private_typeinfo.cpp<br>
<br>
Modified: libcxxabi/trunk/src/private_typeinfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/private_typeinfo.cpp?rev=258249&r1=258248&r2=258249&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/private_typeinfo.cpp?rev=258249&r1=258248&r2=258249&view=diff</a><br>
==============================================================================<br>
--- libcxxabi/trunk/src/private_typeinfo.cpp (original)<br>
+++ libcxxabi/trunk/src/private_typeinfo.cpp Tue Jan 19 17:42:10 2016<br>
@@ -34,9 +34,12 @@<br>
 //<br>
 // _LIBCXX_DYNAMIC_FALLBACK is currently off by default.<br>
<br>
+<br>
+#include <string.h><br>
+<br>
+<br>
 #ifdef _LIBCXX_DYNAMIC_FALLBACK<br>
 #include "abort_message.h"<br>
-#include <string.h><br>
 #include <sys/syslog.h><br>
 #endif<br>
<br>
@@ -57,31 +60,19 @@ namespace __cxxabiv1<br>
<br>
 #pragma GCC visibility push(hidden)<br>
<br>
-#ifdef _LIBCXX_DYNAMIC_FALLBACK<br>
-<br>
 inline<br>
 bool<br>
 is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)<br>
 {<br>
+#ifndef _WIN32<br>
     if (!use_strcmp)<br>
         return x == y;<br>
     return strcmp(x->name(), y->name()) == 0;<br>
-}<br>
-<br>
-#else  // !_LIBCXX_DYNAMIC_FALLBACK<br>
-<br>
-inline<br>
-bool<br>
-is_equal(const std::type_info* x, const std::type_info* y, bool)<br>
-{<br>
-#ifndef _WIN32<br>
-    return x == y;<br>
 #else<br>
     return (x == y) || (strcmp(x->name(), y->name()) == 0);<br>
-#endif<br>
+#endif<br>
 }<br>
<br>
-#endif  // _LIBCXX_DYNAMIC_FALLBACK<br>
<br>
 // __shim_type_info<br>
<br>
@@ -351,8 +342,17 @@ bool<br>
 __pbase_type_info::can_catch(const __shim_type_info* thrown_type,<br>
                              void*&) const<br>
 {<br>
-    return is_equal(this, thrown_type, false) ||<br>
-           is_equal(thrown_type, &typeid(std::nullptr_t), false);<br>
+    if (is_equal(thrown_type, &typeid(std::nullptr_t), false)) return true;<br>
+    bool use_strcmp = this->__flags & (__incomplete_class_mask |<br>
+                                       __incomplete_mask);<br>
+    if (!use_strcmp) {<br>
+        const __pbase_type_info* thrown_pbase = dynamic_cast<const __pbase_type_info*>(<br>
+                thrown_type);<br>
+        if (!thrown_pbase) return false;<br>
+        use_strcmp = thrown_pbase->__flags & (__incomplete_class_mask |<br>
+                                              __incomplete_mask);<br>
+    }<br>
+    return is_equal(this, thrown_type, use_strcmp);<br>
 }<br>
<br>
 #ifdef __clang__<br>
<br>
Added: libcxxabi/trunk/test/incomplete_type.sh.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/incomplete_type.sh.cpp?rev=258249&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/incomplete_type.sh.cpp?rev=258249&view=auto</a><br>
==============================================================================<br>
--- libcxxabi/trunk/test/incomplete_type.sh.cpp (added)<br>
+++ libcxxabi/trunk/test/incomplete_type.sh.cpp Tue Jan 19 17:42:10 2016<br>
@@ -0,0 +1,172 @@<br>
+//===------------------------- incomplete_type.cpp --------------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is dual licensed under the MIT and the University of Illinois Open<br>
+// Source Licenses. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+// <a href="http://mentorembedded.github.io/cxx-abi/abi.html#rtti-layout" rel="noreferrer" target="_blank">http://mentorembedded.github.io/cxx-abi/abi.html#rtti-layout</a><br>
+<br>
+// Two abi::__pbase_type_info objects can always be compared for equality<br>
+// (i.e. of the types represented) or ordering by comparison of their name<br>
+// NTBS addresses. In addition, unless either or both have either of the<br>
+// incomplete flags set, equality can be tested by comparing the type_info<br>
+// addresses.<br>
+<br>
+// RUN: %cxx %flags %compile_flags -c %s -o %t.one.o<br>
+// RUN: %cxx %flags %compile_flags -c %s -o %t.two.o -DTU_ONE<br>
+// RUN: %cxx %flags %link_flags -o %t.exe %t.one.o %t.two.o<br>
+// RUN: %exec %t.exe<br>
+<br>
+#include <stdio.h><br>
+#include <cstring><br>
+#include <cassert><br>
+#include <typeinfo><br>
+<br>
+// Check that the addresses of the typeinfo differ but still compare equal<br>
+// via their NTBS.<br>
+inline void<br>
+AssertIncompleteTypeInfoEquals(std::type_info const& LHS, std::type_info const& RHS)<br>
+{<br>
+  assert(&LHS != &RHS);<br>
+  assert(strcmp(LHS.name(), RHS.name()) == 0);<br>
+}<br>
+<br>
+struct NeverDefined;<br>
+void ThrowNeverDefinedMP();<br>
+std::type_info const& ReturnTypeInfoNeverDefinedMP();<br>
+<br>
+struct IncompleteAtThrow;<br>
+void ThrowIncompleteMP();<br>
+void ThrowIncompletePP();<br>
+void ThrowIncompletePMP();<br>
+std::type_info const& ReturnTypeInfoIncompleteMP();<br>
+std::type_info const& ReturnTypeInfoIncompletePP();<br>
+<br>
+struct CompleteAtThrow;<br>
+void ThrowCompleteMP();<br>
+void ThrowCompletePP();<br>
+void ThrowCompletePMP();<br>
+std::type_info const& ReturnTypeInfoCompleteMP();<br>
+std::type_info const& ReturnTypeInfoCompletePP();<br>
+<br>
+void ThrowNullptr();<br>
+<br>
+#ifndef TU_ONE<br>
+<br>
+void ThrowNeverDefinedMP() { throw (int NeverDefined::*)nullptr; }<br>
+std::type_info const& ReturnTypeInfoNeverDefinedMP() { return typeid(int NeverDefined::*); }<br>
+<br>
+void ThrowIncompleteMP() { throw (int IncompleteAtThrow::*)nullptr; }<br>
+void ThrowIncompletePP() { throw (IncompleteAtThrow**)nullptr; }<br>
+void ThrowIncompletePMP() { throw (int IncompleteAtThrow::**)nullptr; }<br>
+std::type_info const& ReturnTypeInfoIncompleteMP() { return typeid(int IncompleteAtThrow::*); }<br>
+std::type_info const& ReturnTypeInfoIncompletePP() { return typeid(IncompleteAtThrow**); }<br>
+<br>
+struct CompleteAtThrow {};<br>
+void ThrowCompleteMP() { throw (int CompleteAtThrow::*)nullptr; }<br>
+void ThrowCompletePP() { throw (CompleteAtThrow**)nullptr; }<br>
+void ThrowCompletePMP() { throw (int CompleteAtThrow::**)nullptr; }<br>
+std::type_info const& ReturnTypeInfoCompleteMP() { return typeid(int CompleteAtThrow::*); }<br>
+std::type_info const& ReturnTypeInfoCompletePP() { return typeid(CompleteAtThrow**); }<br>
+<br>
+void ThrowNullptr() { throw nullptr; }<br>
+<br>
+#else<br>
+<br>
+struct IncompleteAtThrow {};<br>
+<br>
+int main() {<br>
+  AssertIncompleteTypeInfoEquals(ReturnTypeInfoNeverDefinedMP(), typeid(int NeverDefined::*));<br>
+  try {<br>
+    ThrowNeverDefinedMP();<br>
+    assert(false);<br>
+  } catch (int IncompleteAtThrow::*) {<br>
+    assert(false);<br>
+  } catch (int CompleteAtThrow::*) {<br>
+    assert(false);<br>
+  } catch (int NeverDefined::*) {}<br>
+  AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompleteMP(), typeid(int IncompleteAtThrow::*));<br>
+  try {<br>
+    ThrowIncompleteMP();<br>
+    assert(false);<br>
+  } catch (CompleteAtThrow**) {<br>
+    assert(false);<br>
+  } catch (int CompleteAtThrow::*) {<br>
+    assert(false);<br>
+  } catch (IncompleteAtThrow**) {<br>
+    assert(false);<br>
+  } catch (int IncompleteAtThrow::*) {}<br>
+<br>
+  AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompletePP(), typeid(IncompleteAtThrow**));<br>
+  try {<br>
+    ThrowIncompletePP();<br>
+    assert(false);<br>
+  } catch (int IncompleteAtThrow::*) {<br>
+    assert(false);<br>
+  } catch (IncompleteAtThrow**) {}<br>
+<br>
+  try {<br>
+    ThrowIncompletePMP();<br>
+    assert(false);<br>
+  } catch (int IncompleteAtThrow::*) {<br>
+    assert(false);<br>
+  } catch (IncompleteAtThrow**) {<br>
+    assert(false);<br>
+  } catch (int IncompleteAtThrow::**) {}<br>
+<br>
+  AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompleteMP(), typeid(int CompleteAtThrow::*));<br>
+  try {<br>
+    ThrowCompleteMP();<br>
+    assert(false);<br>
+  } catch (IncompleteAtThrow**) {<br>
+    assert(false);<br>
+  } catch (int IncompleteAtThrow::*) {<br>
+    assert(false);<br>
+  } catch (CompleteAtThrow**) {<br>
+    assert(false);<br>
+  } catch (int CompleteAtThrow::*) {}<br>
+<br>
+  AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompletePP(), typeid(CompleteAtThrow**));<br>
+  try {<br>
+    ThrowCompletePP();<br>
+    assert(false);<br>
+  } catch (IncompleteAtThrow**) {<br>
+    assert(false);<br>
+  } catch (int IncompleteAtThrow::*) {<br>
+    assert(false);<br>
+  } catch (int CompleteAtThrow::*) {<br>
+    assert(false);<br>
+  } catch (CompleteAtThrow**) {}<br>
+<br>
+  try {<br>
+    ThrowCompletePMP();<br>
+    assert(false);<br>
+  } catch (IncompleteAtThrow**) {<br>
+    assert(false);<br>
+  } catch (int IncompleteAtThrow::*) {<br>
+    assert(false);<br>
+  } catch (int CompleteAtThrow::*) {<br>
+    assert(false);<br>
+  } catch (CompleteAtThrow**) {<br>
+    assert(false);<br>
+  } catch (int CompleteAtThrow::**) {}<br>
+<br>
+#if __cplusplus >= 201103L<br>
+  // Catch nullptr as complete type<br>
+  try {<br>
+    ThrowNullptr();<br>
+  } catch (int IncompleteAtThrow::*) {}<br>
+<br>
+  // Catch nullptr as an incomplete type<br>
+  try {<br>
+    ThrowNullptr();<br>
+  } catch (int CompleteAtThrow::*) {}<br>
+  // Catch nullptr as a type that is never complete.<br>
+  try {<br>
+    ThrowNullptr();<br>
+  } catch (int NeverDefined::*) {}<br>
+#endif<br>
+}<br>
+#endif<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>