This is an archive of the discontinued LLVM Phabricator instance.

[libcxx] Fix PR26103 - Error calling is_convertible with incomplete type
ClosedPublic

Authored by mdaniels on Jan 19 2016, 8:44 PM.

Details

Summary

Using std::is_convertible with a pointer to class which contains an incomplete type, and the is_convertible_to is not used (gcc / _LIBCPP_USE_IS_CONVERTIBLE_FALLBACK), is resulting in ADL. Making __test_convert qualified avoid this.

Diff Detail

Event Timeline

mdaniels updated this revision to Diff 45340.Jan 19 2016, 8:44 PM
mdaniels retitled this revision from to [libcxx] Fix PR26103 - Error calling is_convertible with incomplete type.
mdaniels updated this object.
mdaniels added reviewers: mclow.lists, EricWF.

This changes was tested on a 64bit Linux host building llvm with gcc-5.3+libc++, and saw no change to regression runs with gcc-4.8.5, gcc-4.9.3, gcc-5.3, clang-3.4 and clang-3.7.1

EricWF requested changes to this revision.Jan 20 2016, 12:34 AM
EricWF edited edge metadata.

Thanks for the patch! The test case looks good and properly exercises the bug.

However there are a few things that need to be cleaned up. Sorry for the nit-picky review.

include/type_traits
1350

The problem here is that __test_convert is un-qualified so ADL is performed. This seems to instantiate Forward* as seen in your test. Fully qualifying this call has the same effect as your entire patch.

decltype(_VSTD::__is_convertible_imp::__test_convert<_To>(_VSTD::declval<_From>()))

Since I'm not sure that using a constructor is semantically equivalent using a function I would prefer this change instead.

test/std/utilities/meta/meta.rel/is_convertible.pass.cpp
59

This test type can be implemented in a clearer manner. The purpose of Forward is that it causes a compilation error when instantiated. However that's not immediately clear from the name or implementation.

I would go with something like:

template <typename T>
class CannotInstantiate {
  enum { X = T::ThisExpressionWillBlowUp };
};
205

This change is incorrect. We want to run this test in the following configurations:

  • C++11 and beyond for all compilers.
  • C++03 when using Clang's __is_convertible builtin.

The second case is handled by the bit of code you removed.
If your goal was to get this test working with libstdc++ I would change the line to:

#if __cplusplus >= 201103L || (defined(_LIBCPP_VERSION) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK))

215

Can you describe what this test is doing a little more?

For example:

Ensure that Forward is not instantiated by is_convertible when it is not needed. For example Forward is instatiated as a part of ADL lookup for arguments of type Forward*.

This revision now requires changes to proceed.Jan 20 2016, 12:34 AM
mdaniels updated this revision to Diff 45398.Jan 20 2016, 10:24 AM
mdaniels updated this object.
mdaniels edited edge metadata.
mdaniels added inline comments.
include/type_traits
1350

Tests still pass with this, and looks way nicer, consider it done :)

test/std/utilities/meta/meta.rel/is_convertible.pass.cpp
205

I misread the code, I will revert this.

215

Sure thing, thanks for the suggestion.

mdaniels edited edge metadata.Jan 20 2016, 10:25 AM
mdaniels added a subscriber: cfe-commits.
EricWF accepted this revision.Jan 21 2016, 9:09 PM
EricWF edited edge metadata.

LGTM after addressing the IncompleteClass comment.

Thanks for the patch!

test/std/utilities/meta/meta.rel/is_convertible.pass.cpp
216

CannotInstantiate<int>* works too. Using IncompleteClass seems a little distracting because it has nothing to do with the class being incomplete.
The test will fail in the exact same way when a complete class type is given.

This revision is now accepted and ready to land.Jan 21 2016, 9:09 PM
mdaniels updated this revision to Diff 45685.Jan 22 2016, 7:16 AM
mdaniels edited edge metadata.

I dont have commit access, so if the change still looks good, and someone is feeling generous.. :)

EricWF closed this revision.Jan 26 2016, 12:29 PM

Committed as r258852. Thanks for the patch.