[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 --- Comment #14 from Harald van Dijk --- (In reply to Bo Wang from comment #13) > (In reply to Harald van Dijk from comment #12) > > (In reply to Bo Wang from comment #11) > > > I have read the working draft standard of C++20 > > > (https://github.com/cplusplus/draft/tree/c%2B%2B20). > > > > > > Following the subsection "13.9.2 Explicit instantiation" in the section > > > "13.9 Template instantiation and specialization", the statement `template > > > void f();` is an explicit instantiation, which requires instantiating > > > everything in the function. > > > > Where are you getting "everything in the function" from? It seems to say > > rather the opposite in [temp.explicit]p14: > > > > > An explicit instantiation does not constitute a use of a default > > > argument, so default argument instantiation is not done. > > > > Now, the example shows that this was intended to apply to default arguments > > of the function itself, but the actual wording does not limit it to that, so > > I actually think this is a bug in clang, by the current wording this must be > > accepted? > > Please refer to the example in Comment 9 which has no default arguments. Okay, sure, but if we have established that the standard does not say "everything in the function" needs to be instantiated, where does it say that *this* needs to be instantiated? > For the standard, I found this one in "13.9 Template instantiation and > specialization" p6 of C++20, which requires access checking. That explains that the special exception that generally applies to template instantiations does not apply here. This means the usual rules apply, so for instance, you can't refer to a private member of a class unless you're a friend. But for templates, these usual rules apply upon instantiation, so we still need to establish whether or not this is required to be instantiated.
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 --- Comment #13 from Bo Wang --- (In reply to Harald van Dijk from comment #12) > (In reply to Bo Wang from comment #11) > > I have read the working draft standard of C++20 > > (https://github.com/cplusplus/draft/tree/c%2B%2B20). > > > > Following the subsection "13.9.2 Explicit instantiation" in the section > > "13.9 Template instantiation and specialization", the statement `template > > void f();` is an explicit instantiation, which requires instantiating > > everything in the function. > > Where are you getting "everything in the function" from? It seems to say > rather the opposite in [temp.explicit]p14: > > > An explicit instantiation does not constitute a use of a default argument, > > so default argument instantiation is not done. > > Now, the example shows that this was intended to apply to default arguments > of the function itself, but the actual wording does not limit it to that, so > I actually think this is a bug in clang, by the current wording this must be > accepted? Please refer to the example in Comment 9 which has no default arguments. For the standard, I found this one in "13.9 Template instantiation and specialization" p6 of C++20, which requires access checking. > The usual access checking rules do not apply to names in a declaration of an > explicit instantiation or explicit specialization, with the exception of > names > appearing in a function body, default argument, base-clause, member- > specification, enumerator-list, or static data member or variable template > initializer. [Note: In particular, the template arguments and names used in > the > function declarator zincluding parameter types, return types and exception > specifications) may be private types or objects that would normally not be > accessible. —end note] Also, I don't think Clang rejecting these codes is buggy.
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 Harald van Dijk changed: What|Removed |Added CC||harald at gigawatt dot nl --- Comment #12 from Harald van Dijk --- (In reply to Bo Wang from comment #11) > I have read the working draft standard of C++20 > (https://github.com/cplusplus/draft/tree/c%2B%2B20). > > Following the subsection "13.9.2 Explicit instantiation" in the section > "13.9 Template instantiation and specialization", the statement `template > void f();` is an explicit instantiation, which requires instantiating > everything in the function. Where are you getting "everything in the function" from? It seems to say rather the opposite in [temp.explicit]p14: > An explicit instantiation does not constitute a use of a default argument, so > default argument instantiation is not done. Now, the example shows that this was intended to apply to default arguments of the function itself, but the actual wording does not limit it to that, so I actually think this is a bug in clang, by the current wording this must be accepted?
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 --- Comment #11 from Bo Wang --- (In reply to Jakub Jelinek from comment #10) > But again, T::unknown isn't used except in a template which is not > instantiated. > It can't be checked during parsing because T::unknown is dependent and could > very well be well formed if it was instantiated with a different template > argument. > So, does the standard require that all methods of local classes are > instantiated when the containing function template is instantiate (of > course, that can't be the case for methods which are templates on their own)? Thank you for pointing out the critical point. I have read the working draft standard of C++20 (https://github.com/cplusplus/draft/tree/c%2B%2B20). Following the subsection "13.9.2 Explicit instantiation" in the section "13.9 Template instantiation and specialization", the statement `template void f();` is an explicit instantiation, which requires instantiating everything in the function. So we don't need another explicit function call to instantiate it. If my understanding of the standard is correct, the compiler indeed should instantiate and reject this code.
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 --- Comment #10 from Jakub Jelinek --- But again, T::unknown isn't used except in a template which is not instantiated. It can't be checked during parsing because T::unknown is dependent and could very well be well formed if it was instantiated with a different template argument. So, does the standard require that all methods of local classes are instantiated when the containing function template is instantiate (of course, that can't be the case for methods which are templates on their own)?
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 --- Comment #9 from Bo Wang --- I have tried another case that has no default arguments. This one also be accepted. We can find that `T::unknown` is used without type-check. ~~ template void f() { struct S { void g() noexcept(T::unknown); }; } template void f(); ~~ The Godbolt link is here: https://godbolt.org/z/qY6bajaWE
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 --- Comment #8 from Jonathan Wakely --- The point is that the standard does not require a diagnostic for all invalid code. If the rule in the standard is specified as "ill-formed, no diagnostic required" then implementations are allowed to ignore it. For example, because the T::unknown only appears in an unused default argument, or an unused noexcept-specifier. In other words "clang gives an error" does not mean "gcc MUST give an error". But it would be nice if we did give an error, even if it's not required. Either way, I don't think this has anything to do with the "compiler's name-binding process". We just don't care that T::unknown is invalid if we don't use it.
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 --- Comment #7 from Bo Wang --- (In reply to Jakub Jelinek from comment #5) > Probably we just don't instantiate g because nothing needs it. > With > template void f() { > struct S { void g(int n = T::unknown){}; }; > S s; > s.g(); > } > template void f(); > we error: > pr113830.C: In instantiation of ‘void f() [with T = int]’: > pr113830.C:6:22: required from here > 6 | template void f(); > | ^ > pr113830.C:2:32: error: ‘unknown’ is not a member of ‘int’ > 2 | struct S { void g(int n = T::unknown){}; }; > |^~~ > pr113830.C:4:6: note: when instantiating default argument for call to > ‘void f()::S::g(int) [with T = int]’ > 4 | s.g(); > | ~~~^~ > but when one uses s.g(0); instead of s.g(); we accept it as well. As mentioned in Comment 3, the following does not appear to be valid code, but it still compiles. This is unrelated to whether or not the argument is used. ~ template void f() { struct S { void g(int n = T::unknown) noexcept(T::unknown); }; } template void f(); ~
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 --- Comment #6 from Marek Polacek --- (In reply to Bo Wang from comment #4) > (In reply to Marek Polacek from comment #2) > > Bug 66900 is somewhat related in that we also allow int::j. > > I believe these two bugs have different root causes. Bug 113830 should be > due to not instantiating default arguments inside the template function, > especially in instantiating a local class. While Bug 66900 does not have > this issue. Yes, I'm saying they are related, not dups.
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 Jakub Jelinek changed: What|Removed |Added CC||jakub at gcc dot gnu.org --- Comment #5 from Jakub Jelinek --- Probably we just don't instantiate g because nothing needs it. With template void f() { struct S { void g(int n = T::unknown){}; }; S s; s.g(); } template void f(); we error: pr113830.C: In instantiation of ‘void f() [with T = int]’: pr113830.C:6:22: required from here 6 | template void f(); | ^ pr113830.C:2:32: error: ‘unknown’ is not a member of ‘int’ 2 | struct S { void g(int n = T::unknown){}; }; |^~~ pr113830.C:4:6: note: when instantiating default argument for call to ‘void f()::S::g(int) [with T = int]’ 4 | s.g(); | ~~~^~ but when one uses s.g(0); instead of s.g(); we accept it as well.
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 --- Comment #4 from Bo Wang --- (In reply to Marek Polacek from comment #2) > Bug 66900 is somewhat related in that we also allow int::j. I believe these two bugs have different root causes. Bug 113830 should be due to not instantiating default arguments inside the template function, especially in instantiating a local class. While Bug 66900 does not have this issue.
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 --- Comment #3 from Bo Wang --- (In reply to Jonathan Wakely from comment #1) > (In reply to Bo Wang from comment #0) > > It appears that if a template function has an internally defined local class > > that uses a dependent name in its member function, it can cause the > > compiler's name-binding process to get into trouble. > > Or GCC just doesn't check the default argument because it's not used? Please check this one in Godbolt: https://godbolt.org/z/ffj8Pr5n1 It does exist if we use `T::unknow`: ~ template void f() { struct S { void g(int n = T::unknown) noexcept(T::unknown); }; } template void f(); ~ Also, Clang could reject it.
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 Marek Polacek changed: What|Removed |Added See Also||https://gcc.gnu.org/bugzill ||a/show_bug.cgi?id=66900 CC||mpolacek at gcc dot gnu.org --- Comment #2 from Marek Polacek --- Bug 66900 is somewhat related in that we also allow int::j.
[Bug c++/113830] GCC accepts invalid code when instantiating the local class inside a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113830 Jonathan Wakely changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed||2024-02-08 Ever confirmed|0 |1 --- Comment #1 from Jonathan Wakely --- (In reply to Bo Wang from comment #0) > It appears that if a template function has an internally defined local class > that uses a dependent name in its member function, it can cause the > compiler's name-binding process to get into trouble. Or GCC just doesn't check the default argument because it's not used?