upcxx::optional constexpr operators lack assertions

Issue #587 resolved
Dan Bonachea created an issue

Example code:

#include <upcxx/upcxx.hpp>

int main() {
#if 1
  constexpr upcxx::optional<int> co;
  int x = *co; // UB - should assert in C++11 debug mode
  constexpr upcxx::optional<std::pair<int,int>> co2;
  int y = co2->first; // UB - should assert in C++11 debug mode
#else
  upcxx::optional<int> o;
  int x = *o; // UB - asserts in C++11 debug mode
  upcxx::optional<std::pair<int,int>> o2;
  int y = o2->first; // UB - asserts in C++11 debug mode
#endif
}

This demonstrates that the constexpr overloads of member functions upcxx::optional::operator* and upcxx::optional::operator-> are not asserting the validity of the call as intended, due to a mistake in the preprocessor code (discovered via source inspection).

This is a quality-of-implementation defect, as this is UB and the std::optional implementation used for C++17+ also generally will not assert validity.

I believe this is the fix:

--- a/src/optional.hpp
+++ b/src/optional.hpp
@@ -87,7 +87,7 @@ template <class T> inline constexpr typename std::remove_reference<T>::type&& co
 }


-#if UPCXXI_ASSERT_ENABLED
+#if !UPCXXI_ASSERT_ENABLED
 # define UPCXXI_TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
 #else
 // This is used in a constexpr context, so we need to ensure that the

However given the "touchiness" of some compilers around constexpr, this requires re-validation across our full range of supported compilers.

Comments (1)

  1. Log in to comment