Commit de42153e authored by Tom Stellard's avatar Tom Stellard
Browse files

Merging r234254:

------------------------------------------------------------------------
r234254 | ericwf | 2015-04-06 16:03:01 -0700 (Mon, 06 Apr 2015) | 25 lines

[libcxxabi] Disallow Base to Derived conversions for catching pointers to members.

Summary:
I accidentally implemented the 4.11 [conv.mem] conversions for libc++abi in a recent patch. @majnemer pointed out that 5.13 [except.handle] only allows the pointer conversions in 4.10 and not those is 4.11. This patch no longer allows the following example code:

```c++
struct A {};
struct B : public A {};

int main() {
  try {
    throw (int A::*)0;
  } catch (int B::*) {
    // exception caught here.
  }
}
```

Reviewers: mclow.lists, jroelofs, majnemer

Reviewed By: majnemer

Subscribers: majnemer, cfe-commits

Differential Revision: http://reviews.llvm.org/D8845
------------------------------------------------------------------------

llvm-svn: 236866
parent 84c765b2
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -473,11 +473,9 @@ bool __pointer_to_member_type_info::can_catch(
    if (is_equal(__context, thrown_pointer_type->__context, false))
        return true;

    __dynamic_cast_info info = {__context, 0, thrown_pointer_type->__context, -1, 0};
    info.number_of_dst_type = 1;
    __context->has_unambiguous_public_base(&info, adjustedPtr, public_path);
    if (info.path_dst_ptr_to_static_ptr == public_path)
        return true;
    // [except.handle] does not allow the pointer-to-member conversions mentioned
    // in [mem.conv] to take place. For this reason we don't check Derived->Base
    // for Derived->Base conversions.

    return false;
}
+5 −10
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ void test2()
    }
}

// Check that Base -> Derived conversions are allowed.
// Check that Base -> Derived conversions are NOT allowed.
void test3()
{
    try
@@ -90,14 +90,14 @@ void test3()
    }
    catch (der1)
    {
        assert(false);
    }
    catch (md1)
    {
        assert(false);
    }
}

// Check that Base -> Derived conversions are allowed with different cv
// Check that Base -> Derived conversions NOT are allowed with different cv
// qualifiers.
void test4()
{
@@ -107,19 +107,14 @@ void test4()
        assert(false);
    }
    catch (der2)
    {
    }
    catch (...)
    {
        assert(false);
    }

    try
    catch (der1)
    {
        throw &A::j;
        assert(false);
    }
    catch (der1)
    catch (md2)
    {
    }
    catch (...)
+110 −0
Original line number Diff line number Diff line
@@ -18,6 +18,20 @@ struct A
typedef void (A::*mf1)();
typedef void (A::*mf2)() const;

struct B : public A
{
};

typedef void (B::*dmf1)();
typedef void (B::*dmf2)() const;

template <class Tp>
bool can_convert(Tp) { return true; }

template <class>
bool can_convert(...) { return false; }


void test1()
{
    try
@@ -50,8 +64,104 @@ void test2()
    }
}



void test_derived()
{
    try
    {
        throw (mf1)0;
        assert(false);
    }
    catch (dmf2)
    {
       assert(false);
    }
    catch (dmf1)
    {
       assert(false);
    }
    catch (mf1)
    {
    }

    try
    {
        throw (mf2)0;
        assert(false);
    }
    catch (dmf1)
    {
       assert(false);
    }
    catch (dmf2)
    {
       assert(false);
    }
    catch (mf2)
    {
    }

    assert(!can_convert<mf1>((dmf1)0));
    assert(!can_convert<mf2>((dmf1)0));
    try
    {
        throw (dmf1)0;
        assert(false);
    }
    catch (mf2)
    {
       assert(false);
    }
    catch (mf1)
    {
       assert(false);
    }
    catch (...)
    {
    }

    assert(!can_convert<mf1>((dmf2)0));
    assert(!can_convert<mf2>((dmf2)0));
    try
    {
        throw (dmf2)0;
        assert(false);
    }
    catch (mf2)
    {
       assert(false);
    }
    catch (mf1)
    {
        assert(false);
    }
    catch (...)
    {
    }
}

void test_void()
{
    assert(!can_convert<void*>(&A::foo));
    try
    {
        throw &A::foo;
        assert(false);
    }
    catch (void*)
    {
        assert(false);
    }
    catch(...)
    {
    }
}

int main()
{
    test1();
    test2();
    test_derived();
    test_void();
}
+0 −2
Original line number Diff line number Diff line
@@ -140,6 +140,4 @@ int main()
  generate_tests<int A::*, int A::*, 3>()();
  generate_tests<int A::*, void, 2>()();
  generate_tests<void, int A::*, 2>()();
  generate_tests<int Base::*, int Derived::*, 2>()();
  generate_tests<int Derived::*, int Base::*, 2>()();
}