[libcxx-commits] [libc] [compiler-rt] [clang] [llvm] [clang-tools-extra] [flang] [libcxx] [clang] Accept recursive non-dependent calls to functions with deduced return type (PR #75456)
Mariya Podchishchaeva via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jan 5 02:08:09 PST 2024
https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/75456
>From 0e190f131862dd8f4b07891c3ee712a0a163f936 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Thu, 14 Dec 2023 01:33:17 -0800
Subject: [PATCH 1/2] [clang] Accept recursive non-dependent calls to functions
with deduced return type
Treat such calls as dependent since it is much easier to implement.
Fixes https://github.com/llvm/llvm-project/issues/71015
---
clang/docs/ReleaseNotes.rst | 3 ++
clang/lib/AST/ComputeDependence.cpp | 2 ++
clang/lib/Sema/SemaOverload.cpp | 18 ++++++++++
.../SemaCXX/deduced-return-type-cxx14.cpp | 33 +++++++++++++++++++
4 files changed, 56 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 05d59d0da264f3..9ffc7500414981 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -688,6 +688,9 @@ Bug Fixes in This Version
- Fixed false positive error emitted when templated alias inside a class
used private members of the same class.
Fixes (`#41693 <https://github.com/llvm/llvm-project/issues/41693>`_)
+- Clang now accepts recursive non-dependent calls to functions with deduced return
+ type.
+ Fixes (`#71015 <https://github.com/llvm/llvm-project/issues/71015>`_)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
index 097753fd3267b5..584b58473294be 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -603,6 +603,8 @@ ExprDependence clang::computeDependence(PredefinedExpr *E) {
ExprDependence clang::computeDependence(CallExpr *E,
llvm::ArrayRef<Expr *> PreArgs) {
auto D = E->getCallee()->getDependence();
+ if (E->getType()->isDependentType())
+ D |= ExprDependence::Type;
for (auto *A : llvm::ArrayRef(E->getArgs(), E->getNumArgs())) {
if (A)
D |= A->getDependence();
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 5026e1d603e5ee..9fb767101e1eb7 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -13994,6 +13994,24 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
OverloadCandidateSet::iterator Best;
OverloadingResult OverloadResult =
CandidateSet.BestViableFunction(*this, Fn->getBeginLoc(), Best);
+ FunctionDecl *FDecl = Best->Function;
+
+ // Model the case with a call to a templated function whose definition
+ // encloses the call and whose return type contains a placeholder type as if
+ // the UnresolvedLookupExpr was type-dependent.
+ if (OverloadResult == OR_Success && FDecl &&
+ FDecl->isTemplateInstantiation() &&
+ FDecl->getReturnType()->isUndeducedType()) {
+ if (auto TP = FDecl->getTemplateInstantiationPattern(false)) {
+ if (TP->willHaveBody()) {
+ CallExpr *CE =
+ CallExpr::Create(Context, Fn, Args, Context.DependentTy, VK_PRValue,
+ RParenLoc, CurFPFeatureOverrides());
+ result = CE;
+ return result;
+ }
+ }
+ }
return FinishOverloadedCallExpr(*this, S, Fn, ULE, LParenLoc, Args, RParenLoc,
ExecConfig, &CandidateSet, &Best,
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index 6344d1df3fbaeb..1da597499d34f5 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -640,3 +640,36 @@ namespace PR46637 {
template<typename T> struct Y { T x; };
Y<auto() -> auto> y; // expected-error {{'auto' not allowed in template argument}}
}
+
+namespace GH71015 {
+
+// Check that there is no error in case a templated function is recursive and
+// has a placeholder return type.
+struct Node {
+ int value;
+ Node* left;
+ Node* right;
+};
+
+bool parse(const char*);
+Node* parsePrimaryExpr();
+
+auto parseMulExpr(auto node) { // cxx14-error {{'auto' not allowed in function prototype}}
+ if (node == nullptr) node = parsePrimaryExpr();
+ if (!parse("*")) return node;
+ return parseMulExpr(new Node{.left = node, .right = parsePrimaryExpr()});
+}
+
+template <typename T>
+auto parseMulExpr2(T node) {
+ if (node == nullptr) node = parsePrimaryExpr();
+ if (!parse("*")) return node;
+ return parseMulExpr2(new Node{.left = node, .right = parsePrimaryExpr()});
+}
+
+auto f(auto x) { // cxx14-error {{'auto' not allowed in function prototype}}
+ if (x == 0) return 0;
+ return f(1) + 1;
+}
+
+}
>From 9981ec5663fd039cb2ddfc00ae8f1468f2b56d61 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Thu, 4 Jan 2024 02:23:33 -0800
Subject: [PATCH 2/2] Add a testcase
---
clang/test/SemaCXX/deduced-return-type-cxx14.cpp | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index 1da597499d34f5..eac9c587869f55 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -654,7 +654,8 @@ struct Node {
bool parse(const char*);
Node* parsePrimaryExpr();
-auto parseMulExpr(auto node) { // cxx14-error {{'auto' not allowed in function prototype}}
+auto parseMulExpr(auto node) { // cxx14-error {{'auto' not allowed in function prototype}} \
+ // cxx14-note {{not viable}}
if (node == nullptr) node = parsePrimaryExpr();
if (!parse("*")) return node;
return parseMulExpr(new Node{.left = node, .right = parsePrimaryExpr()});
@@ -667,6 +668,18 @@ auto parseMulExpr2(T node) {
return parseMulExpr2(new Node{.left = node, .right = parsePrimaryExpr()});
}
+template <typename T>
+auto parseMulExpr3(T node) { // expected-note {{declared here}}
+ if (node == nullptr) node = parsePrimaryExpr();
+ return parseMulExpr3(new Node{.left = node, .right = parsePrimaryExpr()}); // expected-error {{cannot be used before it is defined}}
+}
+
+void foo() {
+ parseMulExpr(new Node{}); // cxx14-error {{no matching function}}
+ parseMulExpr2(new Node{});
+ parseMulExpr3(new Node{}); // expected-note {{in instantiation}}
+}
+
auto f(auto x) { // cxx14-error {{'auto' not allowed in function prototype}}
if (x == 0) return 0;
return f(1) + 1;
More information about the libcxx-commits
mailing list