Author: ericwf Date: Wed Dec 23 00:35:25 2015 New Revision: 256322 URL: http://llvm.org/viewvc/llvm-project?rev=256322&view=rev Log: Fix PR25898 - Check for incomplete pointers types in can_catch(...)
Added: libcxxabi/trunk/test/incomplete_type.sh.cpp Modified: libcxxabi/trunk/src/private_typeinfo.cpp Modified: libcxxabi/trunk/src/private_typeinfo.cpp URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/private_typeinfo.cpp?rev=256322&r1=256321&r2=256322&view=diff ============================================================================== --- libcxxabi/trunk/src/private_typeinfo.cpp (original) +++ libcxxabi/trunk/src/private_typeinfo.cpp Wed Dec 23 00:35:25 2015 @@ -34,9 +34,12 @@ // // _LIBCXX_DYNAMIC_FALLBACK is currently off by default. + +#include <string.h> + + #ifdef _LIBCXX_DYNAMIC_FALLBACK #include "abort_message.h" -#include <string.h> #include <sys/syslog.h> #endif @@ -57,31 +60,19 @@ namespace __cxxabiv1 #pragma GCC visibility push(hidden) -#ifdef _LIBCXX_DYNAMIC_FALLBACK - inline bool is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp) { +#ifndef _WIN32 if (!use_strcmp) return x == y; return strcmp(x->name(), y->name()) == 0; -} - -#else // !_LIBCXX_DYNAMIC_FALLBACK - -inline -bool -is_equal(const std::type_info* x, const std::type_info* y, bool) -{ -#ifndef _WIN32 - return x == y; #else return (x == y) || (strcmp(x->name(), y->name()) == 0); -#endif +#endif } -#endif // _LIBCXX_DYNAMIC_FALLBACK // __shim_type_info @@ -351,8 +342,17 @@ bool __pbase_type_info::can_catch(const __shim_type_info* thrown_type, void*&) const { - return is_equal(this, thrown_type, false) || - is_equal(thrown_type, &typeid(std::nullptr_t), false); + if (is_equal(thrown_type, &typeid(std::nullptr_t), false)) return true; + bool use_strcmp = this->__flags & (__incomplete_class_mask | + __incomplete_mask); + if (!use_strcmp) { + const __pbase_type_info* thrown_pbase = dynamic_cast<const __pbase_type_info*>( + thrown_type); + if (!thrown_pbase) return false; + use_strcmp = thrown_pbase->__flags & (__incomplete_class_mask | + __incomplete_mask); + } + return is_equal(this, thrown_type, use_strcmp); } #ifdef __clang__ Added: libcxxabi/trunk/test/incomplete_type.sh.cpp URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/incomplete_type.sh.cpp?rev=256322&view=auto ============================================================================== --- libcxxabi/trunk/test/incomplete_type.sh.cpp (added) +++ libcxxabi/trunk/test/incomplete_type.sh.cpp Wed Dec 23 00:35:25 2015 @@ -0,0 +1,83 @@ +//===------------------------- incomplete_type.cpp --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// http://mentorembedded.github.io/cxx-abi/abi.html#rtti-layout + +// Two abi::__pbase_type_info objects can always be compared for equality +// (i.e. of the types represented) or ordering by comparison of their name +// NTBS addresses. In addition, unless either or both have either of the +// incomplete flags set, equality can be tested by comparing the type_info +// addresses. + +// RUN: %cxx %compile_flags -c %s -o %t.one.o +// RUN: %cxx %compile_flags -c %s -o %t.two.o -DTU_ONE +// RUN: %cxx %link_flags -o %t.exe %t.one.o %t.two.o +// RUN: %t.exe + +#include <stdio.h> +#include <cassert> +#include <typeinfo> + +struct NeverDefined; +void ThrowNeverDefined(); + +struct IncompleteAtThrow; +void ThrowIncomplete(); +std::type_info const& ReturnTypeInfoIncomplete(); + +struct CompleteAtThrow; +void ThrowComplete(); +std::type_info const& ReturnTypeInfoComplete(); + +void ThrowNullptr(); + +#ifndef TU_ONE + +void ThrowNeverDefined() { throw (int NeverDefined::*)nullptr; } + +void ThrowIncomplete() { throw (int IncompleteAtThrow::*)nullptr; } +std::type_info const& ReturnTypeInfoIncomplete() { return typeid(int IncompleteAtThrow::*); } + +struct CompleteAtThrow {}; +void ThrowComplete() { throw (int CompleteAtThrow::*)nullptr; } +std::type_info const& ReturnTypeInfoComplete() { return typeid(int CompleteAtThrow::*); } + +void ThrowNullptr() { throw nullptr; } + +#else + +struct IncompleteAtThrow {}; + +int main() { + assert(ReturnTypeInfoIncomplete() != typeid(int IncompleteAtThrow::*)); + try { + ThrowIncomplete(); + } catch (int IncompleteAtThrow::*) {} + + assert(ReturnTypeInfoComplete() != typeid(int CompleteAtThrow::*)); + try { + ThrowComplete(); + } catch (int CompleteAtThrow::*) {} + +#if __cplusplus >= 201103L + // Catch nullptr as complete type + try { + ThrowNullptr(); + } catch (int IncompleteAtThrow::*) {} + + // Catch nullptr as an incomplete type + try { + ThrowNullptr(); + } catch (int CompleteAtThrow::*) {} + // Catch nullptr as a type that is never complete. + try { + ThrowNeverDefined(); + } catch (int NeverDefined::*) {} +#endif +} +#endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits