[clang] [Clang] Support for LibBuiltins with placeholder return types (PR #101702)
Mital Ashok via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 2 09:19:31 PDT 2024
https://github.com/MitalAshok updated https://github.com/llvm/llvm-project/pull/101702
>From 4a7bda13cf7804db1ffce81d3aac77a192585e07 Mon Sep 17 00:00:00 2001
From: Mital Ashok <mital at mitalashok.co.uk>
Date: Fri, 2 Aug 2024 16:27:54 +0100
Subject: [PATCH] [Clang] Support for LibBuiltins with placeholder return types
---
clang/docs/ReleaseNotes.rst | 1 +
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 +-
clang/lib/Sema/SemaType.cpp | 4 +-
.../builtin-std-move-placeholder-return.cpp | 62 +++++++++++++++++++
clang/test/SemaCXX/builtin-std-move.cpp | 4 ++
5 files changed, 71 insertions(+), 2 deletions(-)
create mode 100644 clang/test/SemaCXX/builtin-std-move-placeholder-return.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 25f5bd37bbe94..46adb5bea2b57 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -173,6 +173,7 @@ Bug Fixes to C++ Support
- Clang now correctly parses potentially declarative nested-name-specifiers in pointer-to-member declarators.
- Fix a crash when checking the initialzier of an object that was initialized
with a string literal. (#GH82167)
+- Clang can now use the definition of ``std::forward_like`` in libstdc++ 14.1 and 14.2. (#GH101614)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index f93cd113988ae..2f9b537814661 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4895,7 +4895,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// Never implicitly instantiate a builtin; we don't actually need a function
// body.
if (Function->getBuiltinID() && TSK == TSK_ImplicitInstantiation &&
- !DefinitionRequired)
+ !DefinitionRequired && !Function->getReturnType()->isUndeducedType())
return;
// Don't instantiate a definition if we already have one.
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 6fa39cdccef2b..5a2dfc3228690 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -9468,7 +9468,9 @@ QualType Sema::getDecltypeForExpr(Expr *E) {
}
QualType Sema::BuildDecltypeType(Expr *E, bool AsUnevaluated) {
- assert(!E->hasPlaceholderType() && "unexpected placeholder");
+ assert((!E->hasPlaceholderType() ||
+ E->getType()->isSpecificBuiltinType(BuiltinType::Kind::BuiltinFn)) &&
+ "unexpected placeholder");
if (AsUnevaluated && CodeSynthesisContexts.empty() &&
!E->isInstantiationDependent() && E->HasSideEffects(Context, false)) {
diff --git a/clang/test/SemaCXX/builtin-std-move-placeholder-return.cpp b/clang/test/SemaCXX/builtin-std-move-placeholder-return.cpp
new file mode 100644
index 0000000000000..62446fdf4f3db
--- /dev/null
+++ b/clang/test/SemaCXX/builtin-std-move-placeholder-return.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -std=c++23 -verify %s -DPLACEHOLDER="decltype(auto)"
+// RUN: %clang_cc1 -std=c++23 -verify %s -DPLACEHOLDER="auto&&"
+// RUN: %clang_cc1 -std=c++23 -verify %s -DPLACEHOLDER="True decltype(auto)"
+
+// expected-no-diagnostics
+
+template<class T>
+concept True = true;
+
+namespace std {
+ template<class T>
+ constexpr PLACEHOLDER move(T&& t) noexcept {
+ return static_cast<__remove_reference_t(T)&&>(t);
+ }
+ constexpr PLACEHOLDER move_if_noexcept(auto& t) noexcept {
+ return static_cast<__remove_reference_t(decltype(t))&&>(t);
+ }
+ template<class T, class U>
+ constexpr PLACEHOLDER forward_like(U&& x) noexcept {
+ if constexpr (__is_const(__remove_reference_t(T))) {
+ using copy_const = const __remove_reference_t(U);
+ if constexpr (__is_rvalue_reference(T&&)) {
+ using V = __remove_reference_t(copy_const)&&;
+ return static_cast<V>(x);
+ } else {
+ using V = copy_const&;
+ return static_cast<V>(x);
+ }
+ } else {
+ using copy_const = __remove_reference_t(U);
+ if constexpr (__is_rvalue_reference(T&&)) {
+ using V = __remove_reference_t(copy_const)&&;
+ return static_cast<V>(x);
+ } else {
+ using V = copy_const&;
+ return static_cast<V>(x);
+ }
+ }
+ }
+}
+
+namespace GH101614 {
+int i;
+static_assert(__is_same(decltype(std::move(i)), int&&));
+static_assert(__is_same(decltype(std::move_if_noexcept(i)), int&&));
+static_assert(__is_same(decltype(std::forward_like<char>(i)), int&&));
+static_assert(__is_same(decltype(std::forward_like<char&>(i)), int&));
+
+constexpr bool is_i(int&& x) { return &x == &i; }
+void is_i(int&) = delete;
+void is_i(auto&&) = delete;
+
+static_assert(is_i(std::move(i)));
+static_assert(is_i(std::move_if_noexcept(i)));
+static_assert(is_i(std::forward_like<char>(i)));
+static_assert(&std::forward_like<char&>(i) == &i);
+
+// These types are incorrect, but make sure the types as declared are used
+static_assert(__is_same(decltype(std::move<int(&)()>), auto(int(&)()) noexcept -> int(&)()));
+static_assert(__is_same(decltype(std::move_if_noexcept<int(&)()>), auto(int(&)()) noexcept -> int(&)()));
+static_assert(__is_same(decltype(std::forward_like<int, int(&)()>), auto(int(&)()) noexcept -> int(&)()));
+} // namespace GH101614
diff --git a/clang/test/SemaCXX/builtin-std-move.cpp b/clang/test/SemaCXX/builtin-std-move.cpp
index a2ae21986308a..da85703c5d58e 100644
--- a/clang/test/SemaCXX/builtin-std-move.cpp
+++ b/clang/test/SemaCXX/builtin-std-move.cpp
@@ -172,3 +172,7 @@ namespace std {
template<typename T> int &move(T);
}
int bad_signature = std::move(0); // expected-error {{unsupported signature for 'std::move<int>'}}
+
+namespace GH101690 {
+decltype(std::move_if_noexcept<int>)* p = nullptr;
+}
More information about the cfe-commits
mailing list