typename add_lvalue_reference<element_type>::type
operator*() const noexcept(noexcept(*std::declval<pointer>()))
{
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__reference_converts_from_temporary)
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4148. unique_ptr::operator* should not allow dangling references
+ using _ResT = typename add_lvalue_reference<element_type>::type;
+ using _DerefT = decltype(*get());
+ static_assert(!__reference_converts_from_temporary(_ResT, _DerefT),
+ "operator* must not return a dangling reference");
+#endif
__glibcxx_assert(get() != pointer());
return *get();
}
--- /dev/null
+// { dg-do compile { target c++11 } }
+
+// LWG 4148. unique_ptr::operator* should not allow dangling references
+
+#include <memory>
+
+struct pointer
+{
+ pointer() { }
+ pointer(std::nullptr_t) { }
+ int operator*() const { return 0; }
+ bool operator==(pointer) const { return true; }
+ bool operator==(std::nullptr_t) const { return false; }
+#ifndef __cpp_lib_three_way_comparison
+ bool operator!=(pointer) const { return false; }
+ bool operator!=(std::nullptr_t) const { return true; }
+#endif
+};
+
+struct Deleter
+{
+ using pointer = ::pointer;
+ void operator()(pointer) const { }
+};
+
+std::unique_ptr<const int, Deleter> up;
+int i = *up; // { dg-error "here" }
+// { dg-error "dangling reference" "" { target *-*-* } 0 }
+
+// { dg-warning "returning reference to temporary" "" { target c++23_down } 0 }
+// { dg-error "returning reference to temporary" "" { target c++26 } 0 }