aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2025-03-11 17:29:01 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2025-03-12 10:12:36 +0000
commit8ff7ff1a0691b7b409aa31c8f6dfcefec3e4720b (patch)
tree843db2927ffe6681202c3c97ae0d90f5c801392a /libstdc++-v3/testsuite
parent04815ae0a2b27895411506813db3a8b460be1d6d (diff)
downloadgcc-8ff7ff1a0691b7b409aa31c8f6dfcefec3e4720b.zip
gcc-8ff7ff1a0691b7b409aa31c8f6dfcefec3e4720b.tar.gz
gcc-8ff7ff1a0691b7b409aa31c8f6dfcefec3e4720b.tar.bz2
libstdc++: Prevent dangling references in std::unique_ptr::operator*
LWG 4148 (approved in Wrocław, November 2024) makes it ill-formed to dereference a std::unique_ptr if that would return a dangling reference. That can happen with a custom pointer type and a const-qualified element_type, such that std::add_lvalue_reference_t<element_type> is a reference-to-const that could bind to a short-lived temporary. In C++26 the compiler diagnoses this as an error anyway: bits/unique_ptr.h:457:16: error: returning reference to temporary [-Wreturn-local-addr] But that can be disabled with -Wno-return-local-addr so the static_assert ensures it is enforced consistently. libstdc++-v3/ChangeLog: * include/bits/unique_ptr.h (unique_ptr::operator*): Add static_assert to check for dangling reference, as per LWG 4148. * testsuite/20_util/unique_ptr/lwg4148.cc: New test. Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Diffstat (limited to 'libstdc++-v3/testsuite')
-rw-r--r--libstdc++-v3/testsuite/20_util/unique_ptr/lwg4148.cc31
1 files changed, 31 insertions, 0 deletions
diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/lwg4148.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/lwg4148.cc
new file mode 100644
index 0000000..c70d7a6
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/unique_ptr/lwg4148.cc
@@ -0,0 +1,31 @@
+// { 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 }