[libcxx-commits] [libcxx] c555a12 - [libc++] Make sure std::declval() produces an error when ODR-used

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Thu Oct 26 08:27:20 PDT 2023


Author: Igor Zhukov
Date: 2023-10-26T11:27:12-04:00
New Revision: c555a12377307909bd47e5de798059089eaa3f85

URL: https://github.com/llvm/llvm-project/commit/c555a12377307909bd47e5de798059089eaa3f85
DIFF: https://github.com/llvm/llvm-project/commit/c555a12377307909bd47e5de798059089eaa3f85.diff

LOG: [libc++] Make sure std::declval() produces an error when ODR-used

Fixes https://github.com/llvm/llvm-project/issues/61202

Differential Revision: https://reviews.llvm.org/D145376

Added: 
    libcxx/test/std/utilities/utility/declval/declval.verify.cpp

Modified: 
    libcxx/include/__utility/declval.h
    libcxx/test/std/input.output/iostream.format/output.streams/ostream/deleted_output_functions.verify.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__utility/declval.h b/libcxx/include/__utility/declval.h
index c2f4bec1328277c..d0856b8afa4db9e 100644
--- a/libcxx/include/__utility/declval.h
+++ b/libcxx/include/__utility/declval.h
@@ -27,7 +27,11 @@ _Tp __declval(long);
 _LIBCPP_SUPPRESS_DEPRECATED_POP
 
 template <class _Tp>
-decltype(std::__declval<_Tp>(0)) declval() _NOEXCEPT;
+_LIBCPP_HIDE_FROM_ABI decltype(std::__declval<_Tp>(0)) declval() _NOEXCEPT {
+  static_assert(!__is_same(_Tp, _Tp),
+                "std::declval can only be used in an unevaluated context. "
+                "It's likely that your current usage is trying to extract a value from the function.");
+}
 
 _LIBCPP_END_NAMESPACE_STD
 

diff  --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream/deleted_output_functions.verify.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream/deleted_output_functions.verify.cpp
index d8d2a94791b3ab0..2916a94cdcd6f04 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream/deleted_output_functions.verify.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream/deleted_output_functions.verify.cpp
@@ -18,38 +18,47 @@
 
 void f() {
   std::ostringstream s;
+#ifndef TEST_HAS_NO_CHAR8_T
+  char8_t c8_s[]       = u8"test";
+  const char8_t* c8_cs = u8"test";
+#endif
+  char16_t c16_s[]       = u"test";
+  const char16_t* c16_cs = u"test";
+  char32_t c32_s[]       = U"test";
+  const char32_t* c32_cs = U"test";
 
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-
-  s << wchar_t();                      // expected-error {{overload resolution selected deleted operator '<<'}}
-  s << std::declval<wchar_t*>();       // expected-error {{overload resolution selected deleted operator '<<'}}
-  s << std::declval<const wchar_t*>(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  wchar_t w_s[]       = L"test";
+  const wchar_t* w_cs = L"test";
+  s << wchar_t(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  s << w_s;       // expected-error {{overload resolution selected deleted operator '<<'}}
+  s << w_cs;      // expected-error {{overload resolution selected deleted operator '<<'}}
 
   std::wostringstream sw;
 #  ifndef TEST_HAS_NO_CHAR8_T
-  sw << char8_t();                      // expected-error {{overload resolution selected deleted operator '<<'}}
-  sw << std::declval<char8_t*>();       // expected-error {{overload resolution selected deleted operator '<<'}}
-  sw << std::declval<const char8_t*>(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  sw << char8_t(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  sw << c8_s;      // expected-error {{overload resolution selected deleted operator '<<'}}
+  sw << c8_cs;     // expected-error {{overload resolution selected deleted operator '<<'}}
 #  endif
 
-  sw << char16_t();                      // expected-error {{overload resolution selected deleted operator '<<'}}
-  sw << std::declval<char16_t*>();       // expected-error {{overload resolution selected deleted operator '<<'}}
-  sw << std::declval<const char16_t*>(); // expected-error {{overload resolution selected deleted operator '<<'}}
-  sw << char32_t();                      // expected-error {{overload resolution selected deleted operator '<<'}}
-  sw << std::declval<char32_t*>();       // expected-error {{overload resolution selected deleted operator '<<'}}
-  sw << std::declval<const char32_t*>(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  sw << char16_t(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  sw << c16_s;      // expected-error {{overload resolution selected deleted operator '<<'}}
+  sw << c16_cs;     // expected-error {{overload resolution selected deleted operator '<<'}}
+  sw << char32_t(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  sw << c32_s;      // expected-error {{overload resolution selected deleted operator '<<'}}
+  sw << c32_cs;     // expected-error {{overload resolution selected deleted operator '<<'}}
 
 #endif // TEST_HAS_NO_WIDE_CHARACTERS
 
 #ifndef TEST_HAS_NO_CHAR8_T
-  s << char8_t();                      // expected-error {{overload resolution selected deleted operator '<<'}}
-  s << std::declval<char8_t*>();       // expected-error {{overload resolution selected deleted operator '<<'}}
-  s << std::declval<const char8_t*>(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  s << char8_t(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  s << c8_s;      // expected-error {{overload resolution selected deleted operator '<<'}}
+  s << c8_cs;     // expected-error {{overload resolution selected deleted operator '<<'}}
 #endif
-  s << char16_t();                      // expected-error {{overload resolution selected deleted operator '<<'}}
-  s << std::declval<char16_t*>();       // expected-error {{overload resolution selected deleted operator '<<'}}
-  s << std::declval<const char16_t*>(); // expected-error {{overload resolution selected deleted operator '<<'}}
-  s << char32_t();                      // expected-error {{overload resolution selected deleted operator '<<'}}
-  s << std::declval<char32_t*>();       // expected-error {{overload resolution selected deleted operator '<<'}}
-  s << std::declval<const char32_t*>(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  s << char16_t(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  s << c16_s;      // expected-error {{overload resolution selected deleted operator '<<'}}
+  s << c16_cs;     // expected-error {{overload resolution selected deleted operator '<<'}}
+  s << char32_t(); // expected-error {{overload resolution selected deleted operator '<<'}}
+  s << c32_s;      // expected-error {{overload resolution selected deleted operator '<<'}}
+  s << c32_cs;     // expected-error {{overload resolution selected deleted operator '<<'}}
 }

diff  --git a/libcxx/test/std/utilities/utility/declval/declval.verify.cpp b/libcxx/test/std/utilities/utility/declval/declval.verify.cpp
new file mode 100644
index 000000000000000..a2bd1992aaa8376
--- /dev/null
+++ b/libcxx/test/std/utilities/utility/declval/declval.verify.cpp
@@ -0,0 +1,16 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <utility>
+
+// template <class T> typename add_rvalue_reference<T>::type declval() noexcept;
+
+#include <utility>
+
+int x = std::declval<
+    int>(); // expected-error-re@*:* {{static assertion failed{{.*}}std::declval can only be used in an unevaluated context.}}


        


More information about the libcxx-commits mailing list