Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More checks for non-compilable code, plus fix for span #1180

Merged
merged 18 commits into from
Jan 4, 2025

Conversation

beinhaerter
Copy link
Contributor

@beinhaerter beinhaerter commented Dec 28, 2024

  • Bugfix: templated versions of span::first(), span::last() and span::subspan() now fail to compile if more elements than available are being extracted from a static sized span; previously it compiled and Expects failed during runtime
  • Remove some of the checks in #ifdef CONFIRM_COMPILATION_ERRORS and add compile time checks for these tests.
  • Acitvate some commented out checks.
  • Activate some deactivated checks depending on the platform
  • Make some death checks simpler to only check the function call that is needed to trigger the death.
  • clang-format

@beinhaerter
Copy link
Contributor Author

beinhaerter commented Dec 28, 2024

I was not able to replace all checks in the touched files.

Functions where the type constraints are not checked with enable_if but with a static_assert in the function cannot be checked with the SFINAE trick. For example decltype(gsl::to_byte(char{})) x; compiles. The compilers seems to see the valid function signature, but as the function is not called, it does not compile the function body and thus ignores the static_assert(std::is_same<T, unsigned char>::value, ...);. Visibility/availability of the function does not mean compilability.

Classes where a type constraint is not checked with enable_if but with a static_assert in the class cannot be checked with the SFINAE trick. For example not_null<int> triggers the class wide static_assert(details::is_comparable_to_nullptr<T>::value, "T cannot be compared to nullptr."); even in SFINAE context.

The static_assert checks in class and function are nice for regular users as they give better warnings, but they break unit tests. How do we want to proceed with them? I am curious what your experts think about it.

@beinhaerter beinhaerter force-pushed the unit_test_compilation_error branch 5 times, most recently from 2c70176 to e329a72 Compare December 30, 2024 12:57
@beinhaerter beinhaerter force-pushed the unit_test_compilation_error branch 2 times, most recently from d0cd8ee to 57e5a91 Compare December 30, 2024 13:12
@beinhaerter beinhaerter force-pushed the unit_test_compilation_error branch 3 times, most recently from b2e7ddc to e65ece0 Compare December 30, 2024 14:23
@beinhaerter
Copy link
Contributor Author

If desired, I can also move the static_asserts into the functions where the old #ifdef CONFIRM-COMPILATION_ERRORS were. That might be better for getting a good overview and structuring.

@beinhaerter beinhaerter force-pushed the unit_test_compilation_error branch 3 times, most recently from 141cd59 to 466e3f7 Compare December 30, 2024 16:20
@beinhaerter beinhaerter force-pushed the unit_test_compilation_error branch 5 times, most recently from 711572c to a1d2c73 Compare January 1, 2025 16:42
@beinhaerter
Copy link
Contributor Author

If desired, I can also move the static_asserts into the functions where the old #ifdef CONFIRM-COMPILATION_ERRORS were. That might be better for getting a good overview and structuring.

Done.

@beinhaerter beinhaerter force-pushed the unit_test_compilation_error branch 3 times, most recently from c855f7e to 02c02cc Compare January 1, 2025 17:00
}
static_assert(TypeDeductionCtorCompilesFor<void*>, "TypeDeductionCtorCompilesFor<void*>");
#if defined(_MSC_VER)
// Fails on gcc, clang, xcode, VS clang with
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pipeline stops at the first error. I did not check if this compiles for any of the gcc/clang/xcode versions.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. At first glance this looks like an "accepts invalid" for MSVC. We shouldn't be able to create a gsl::not_null<nullptr_t>. I will investigate further then raise the issue internally.

@@ -216,6 +222,12 @@ TEST(span_test, from_pointer_length_constructor)

TEST(span_test, from_pointer_pointer_construction)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function has three commented out checks with comments "// this will fail the std::distance() precondition, which asserts on MSVC debug builds". I tried to activate the tests on different platforms, but then the tests failed. I could not match the comment with the death behaviour of the code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not match the comment with the death behaviour of the code.

How does it fail today? I don't see a std::distance call in gsl/span, so I wonder if the comment is just out of date.

Probably also worth noting that the &arr[1] expression is UB so if compilers treat it differently, it may not be a compiler bug.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that two of the three EXPECT_DEATH failed because no death occured. The pipeline said line 296 and line 273 failed.

Because of ammending commits I cannot match failed pipelines to still existing commits. But I think these were the test 2 and 3, not the first one.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests 2 and 3 are identical? Let me know if I'm missing something. Test 1 is definitely UB.

I think we should delete test 1 and uncomment either test 2 or test 3 (and delete the other).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For std::span all three tests are UB.

This is the implementation of the gsl::span ctor.

    template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != dynamic_extent, int> = 0>
    constexpr explicit span(pointer firstElem, pointer lastElem) noexcept
        : storage_(firstElem, narrow_cast<std::size_t>(lastElem - firstElem))
    {
        Expects(lastElem - firstElem == static_cast<difference_type>(Extent));
    }

I think for GSL the relevant point is lastElem - firstElem. For the first case (&arr[0] - &arr[1]) this is OK. The length store in storage_ is not fine, but the Expects triggers.
For the checks with a nullptr the pointer subtraction should be a problem (the pointers do not point into the same object -> UB).

If I don't miss anything then test one is a test that we can activate, but tests two and three should be deleted or left commented out.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all tests should be deleted. It will be confusing to have tests that may start to fail with a compiler update.

If you see value in keeping them commented out for reference, that's fine. But the false comments about std::distance should be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests 2 and 3 are identical? Let me know if I'm missing something. Test 1 is definitely UB.

Your godbolt test is range nullptr[1]..nullptr[0]. Test 1 is arr[1]..arr[0] where arr is a C style array.

I delete the tests 2 and 3. For test 1 you can decide. I think we do not need to assure this behaviour, but if we want to, it does not hurt.

@beinhaerter beinhaerter force-pushed the unit_test_compilation_error branch from 7b8563d to 4279da5 Compare January 2, 2025 09:44
@beinhaerter beinhaerter changed the title More checks for non-compilable code More checks for non-compilable code, plus fix for span Jan 2, 2025
@carsonRadtke carsonRadtke added Type: Enhancement Suggests an improvement or new feature Type: Infra Changes to build system, tests, or pipelines Status: Review Needed Needs review from GSL maintainers labels Jan 3, 2025
Copy link
Collaborator

@carsonRadtke carsonRadtke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing macro'd out code for static_asserts is a great change, thanks!

Just a couple comments/questions/suggestions. Once those are resolved, it will be ready to merge.

}
static_assert(TypeDeductionCtorCompilesFor<void*>, "TypeDeductionCtorCompilesFor<void*>");
#if defined(_MSC_VER)
// Fails on gcc, clang, xcode, VS clang with
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. At first glance this looks like an "accepts invalid" for MSVC. We shouldn't be able to create a gsl::not_null<nullptr_t>. I will investigate further then raise the issue internally.

@@ -216,6 +222,12 @@ TEST(span_test, from_pointer_length_constructor)

TEST(span_test, from_pointer_pointer_construction)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not match the comment with the death behaviour of the code.

How does it fail today? I don't see a std::distance call in gsl/span, so I wonder if the comment is just out of date.

Probably also worth noting that the &arr[1] expression is UB so if compilers treat it differently, it may not be a compiler bug.

@carsonRadtke
Copy link
Collaborator

carsonRadtke commented Jan 3, 2025

I opened #1181 to address the failing checks.

I will merge ASAP.

Edit: merged

Werner Henze and others added 12 commits January 3, 2025 19:08

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
- Remove some of the checks in `#ifdef CONFIRM_COMPILATION_ERRORS` and add compile time checks for these tests.
- `algorithm_tests.cpp` and `span_test.cpp` have not been touched.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
plus more unit tests for these functions
@beinhaerter beinhaerter force-pushed the unit_test_compilation_error branch from 97b7c00 to e31f8d7 Compare January 3, 2025 18:09
@carsonRadtke
Copy link
Collaborator

Looks good! Thanks for the PR and thanks for making all the requested changes :)

@carsonRadtke carsonRadtke merged commit 1cdb8d2 into microsoft:main Jan 4, 2025
83 checks passed
@beinhaerter beinhaerter deleted the unit_test_compilation_error branch January 6, 2025 14:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Review Needed Needs review from GSL maintainers Type: Enhancement Suggests an improvement or new feature Type: Infra Changes to build system, tests, or pipelines
Projects
Development

Successfully merging this pull request may close these issues.

None yet

2 participants