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