-
Notifications
You must be signed in to change notification settings - Fork 10.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang] seems like bug with return type deduction in case of recursive function (works in GCC) #71015
Comments
@llvm/issue-subscribers-clang-frontend Author: Богдан (vampyrofangclub)
Here is an example
```cpp
struct Node {
int value;
Node* left;
Node* right;
};
bool parse(const char*); auto parseMulExpr(auto node) { int main(){
<source>:13:10: error: function 'parseMulExpr<Node *>' with deduced return type cannot be used before it is defined
|
This looks like a clang bug to me: https://godbolt.org/z/4dr7r3h3z As per dcl.spec.auto p11 once we have seen a non-discarded return statement where the type was deduced we should be good. If we use what should be the equivalent templated version it is fine: template <typename T>
auto parseMulExpr2(T node) {
if (node == nullptr) node = parsePrimaryExpr();
if (!parse("*")) return node;
return parseMulExpr2<T>(new Node{.left = node, .right = parsePrimaryExpr()});
} |
CC @Fznamznon if you are interested |
There is also https://eel.is/c++draft/dcl.spec.auto#general-12 which says that for templated function return type deduction only happens when the definition is instantiated, that is the reason why return type is not deduced by clang atm: llvm-project/clang/lib/Sema/SemaStmt.cpp Line 3806 in 1127656
So, is the error actually a bug? Another problem is, even if we remove this early-exit, the function's type will be updated, but there is another problem. Recursive call to the function causes its implicit instantiation, but template instantiator doesn't seem to care about function type, it only cares about function Later on, when we check that function type is deduced, try to deduce and fail because function is not yet fully defined.
Regarding why templated case works:
This only works because recursive call in the last return statement is considered as dependent due to presence of That also simplifies the reproducer - https://godbolt.org/z/4voeehxjn. So, not sure how this can be fixed atm, help is appreciated. |
Maybe we need to check that we are not in the middle of performing instantantiation in addition of this check (and if we are, we should not return) |
@zygoloid does this sound correct to you? |
Per https://eel.is/c++draft/temp.dep.expr#3, the recursive call is not type-dependent, so we need a type for it in the template instantiation. That seems like a bug in the language rules to me. I think the proper behavior here is probably that we should treat a call to a templated function whose definition encloses the call and whose return type contains a placeholder type as being type-dependent. From an implementation standpoint, I think it would add complexity to allow the template to contain a |
…d return type Treat such calls as dependent since it is much easier to implement. Fixes llvm#71015
Here is an example
Clang gives this error
https://godbolt.org/z/7WTYYben5
The text was updated successfully, but these errors were encountered: