[libcxx-commits] [libcxx] e43c93d - Don't treat 'T &forward(T&&)' as builtin.
Richard Smith via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Apr 18 11:11:33 PDT 2022
Author: Richard Smith
Date: 2022-04-18T11:11:21-07:00
New Revision: e43c93dd63cca295ef26ab69cd305816a71d45fd
URL: https://github.com/llvm/llvm-project/commit/e43c93dd63cca295ef26ab69cd305816a71d45fd
DIFF: https://github.com/llvm/llvm-project/commit/e43c93dd63cca295ef26ab69cd305816a71d45fd.diff
LOG: Don't treat 'T &forward(T&&)' as builtin.
This allows the standard library to diagnose it properly. Suppress
warning in libc++ testsuite for unused result of call to std::forward.
Added:
Modified:
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/SemaCXX/builtin-std-move.cpp
libcxx/test/std/utilities/utility/forward/forward.fail.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 8b0147fc66c36..f11a1748e5c68 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -621,6 +621,20 @@ static bool isRelevantAttr(Sema &S, const Decl *D, const Attr *A) {
return true;
}
+ if (const auto *BA = dyn_cast<BuiltinAttr>(A)) {
+ // Do not treat 'std::forward' as a builtin if it takes an rvalue reference
+ // type and returns an lvalue reference type. The library implementation
+ // will produce an error in this case; don't get in its way.
+ if (BA->getID() == Builtin::BIforward) {
+ const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (FD && FD->getNumParams() >= 1 &&
+ FD->getParamDecl(0)->getType()->isRValueReferenceType() &&
+ FD->getReturnType()->isLValueReferenceType()) {
+ return false;
+ }
+ }
+ }
+
return true;
}
diff --git a/clang/test/SemaCXX/builtin-std-move.cpp b/clang/test/SemaCXX/builtin-std-move.cpp
index a53e57c86c14c..7f1b01e43d788 100644
--- a/clang/test/SemaCXX/builtin-std-move.cpp
+++ b/clang/test/SemaCXX/builtin-std-move.cpp
@@ -30,11 +30,18 @@ namespace std {
template<typename T> struct remove_reference<T&> { using type = T; };
template<typename T> struct remove_reference<T&&> { using type = T; };
+ template<typename T> struct is_lvalue_reference { static constexpr bool value = false; };
+ template<typename T> struct is_lvalue_reference<T&> { static constexpr bool value = true; };
+
template<typename T> CONSTEXPR T &&forward(typename remove_reference<T>::type &x) {
static_assert(T::moveable, "instantiated forward"); // expected-error {{no member named 'moveable' in 'B'}}
// expected-error at -1 {{no member named 'moveable' in 'C'}}
return static_cast<T&&>(x);
}
+ template<typename T> CONSTEXPR T &&forward(typename remove_reference<T>::type &&x) {
+ static_assert(!is_lvalue_reference<T>::value, "should not forward rval as lval"); // expected-error {{static_assert failed}}
+ return static_cast<T&&>(x);
+ }
template<typename T> CONSTEXPR const T &as_const(T &x) {
static_assert(T::moveable, "instantiated as_const"); // expected-error {{no member named 'moveable' in 'B'}}
@@ -76,6 +83,11 @@ static_assert(f({}), "should be constexpr");
// expected-note@#call {{}}
#endif
+A &forward_rval_as_lval() {
+ std::forward<A&&>(A()); // expected-warning {{const attribute}}
+ return std::forward<A&>(A()); // expected-note {{instantiation of}}
+}
+
struct B {};
B &&(*pMove)(B&) = std::move; // #1 expected-note {{instantiation of}}
B &&(*pMoveIfNoexcept)(B&) = &std::move_if_noexcept; // #2 expected-note {{instantiation of}}
diff --git a/libcxx/test/std/utilities/utility/forward/forward.fail.cpp b/libcxx/test/std/utilities/utility/forward/forward.fail.cpp
index 4d7790a751481..f913b835c2248 100644
--- a/libcxx/test/std/utilities/utility/forward/forward.fail.cpp
+++ b/libcxx/test/std/utilities/utility/forward/forward.fail.cpp
@@ -22,7 +22,7 @@ const A csource() {return A();}
int main(int, char**)
{
{
- std::forward<A&>(source()); // expected-note {{requested here}}
+ (void)std::forward<A&>(source()); // expected-note {{requested here}}
// expected-error-re@*:* 1 {{static_assert failed{{.*}} "cannot forward an rvalue as an lvalue"}}
}
{
More information about the libcxx-commits
mailing list