================ @@ -186,3 +186,74 @@ class E { #endif template<typename T> using D = int; // expected-note {{declared here}} E<D> ed; // expected-note {{instantiation of}} + +namespace non_functions { + +#if __cplusplus >= 201103L +namespace PR88832 { +template <typename T> struct O { + static const T v = 0; +}; + +struct P { + template <typename T> using I = typename O<T>::v; // #TypeAlias +}; + +struct Q { + template <typename T> int foo() { + return T::template I<int>; // expected-error {{'P::I' is expected to be a non-type template, but instantiated to a type alias template}} + // expected-note@#TypeAlias {{type alias template declared here}} + } +}; + +int bar() { + return Q().foo<P>(); // expected-note-re {{function template specialization {{.*}} requested here}} +} + +} // namespace PR88832 +#endif + +namespace PR63243 { + +namespace std { +template <class T> struct add_pointer { // #add_pointer +}; +} // namespace std + +class A {}; + +int main() { + std::__add_pointer<A>::type ptr; // #ill-formed-decl + // expected-error@#ill-formed-decl {{no template named '__add_pointer'}} + // expected-note@#add_pointer {{'add_pointer' declared here}} + // expected-error@#ill-formed-decl {{expected ';' after expression}} + // expected-error@#ill-formed-decl {{no type named 'type' in the global namespace}} + // expected-error@#ill-formed-decl {{'std::add_pointer' is expected to be a non-type template, but instantiated to a class template}} ---------------- zyn0217 wrote:
> As far as this diagnostic, can you spend a little time to evaluate how much > work it is to fix that? It is particularly awkward. I have looked into it a bit more, and I found it is a consequence of not handling `TRANSFORM_TYPE_TRAIT`s as scope specifiers, which was introduced in e9ef45635. Let's explain the difference with an example: ```cpp namespace std { struct add_pointer {}; } void foo() { std::__add_pointer<int>::type ptr; std::Add_pointer<int>::type ptr2; } ``` we would end up seeing different diagnostics on two declarations `ptr` and `ptr2`: the first is what was crashing previously, because `__add_pointer` is actually a keyword rather than an identifier like `Add_pointer`. As a result, we would bail out when we see `__add_pointer` in `ParseOptionalCXXScopeSpecifier`, and we would continue parsing it as a `TemplateIdExpr`, which gave us a crash as well as a spurious diagnostic saying we're missing a semicolon after `<int>`. For comparison, the second case would keep parsing until we encounter the semicolon after `ptr2`. This results in a better diagnostic even after the typo correction. I think a fix would be to add a handling logic to `ParseOptionalCXXScopeSpecifier` like what we did in e9ef45635: ```cpp switch (Tok.getKind()) { #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: #include "clang/Basic/TransformTypeTraits.def" if (NextToken().is(tok::less)) { Tok.setKind(tok::identifier); Diag(Tok, diag::ext_keyword_as_ident) << Tok.getIdentifierInfo()->getName() << 0; continue; } LLVM_FALLTHROUGH; default: break; } ``` https://github.com/llvm/llvm-project/pull/89019 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits