[clang-tools-extra] [clang] [llvm] [clang] Accept recursive non-dependent calls to functions with deduced return type (PR #75456)

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 4 12:52:32 PST 2024


================
@@ -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()});
----------------
zygoloid wrote:

I think that's fine, and it's what I expected. While we could try to reject in the template definition if we see a recursive call prior to the end of the first `return` statement, I don't think it's worth the added complexity.

I *think* what GCC's doing here is that it's treating the recursive call as dependent in much the same way that Clang does with this patch, but then performing an instantiation of the function template specialization `parseMulExpr<Node*>` *after* it finishes processing the template definition -- so it's also not eagerly diagnosing the problem. (Clang suppresses performing recursive non-dependent function template instantiations until the template has a point of instantiation outside itself, which GCC doesn't seem to do.) But I could be wrong.

https://github.com/llvm/llvm-project/pull/75456


More information about the cfe-commits mailing list