tbaeder created this revision. tbaeder added reviewers: dblaikie, aaron.ballman. Herald added a project: All. tbaeder requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
This fixes https://github.com/llvm/llvm-project/issues/55962 i.e. instead of the output being ./test.cpp:5:9: error: 'x' is not a class, namespace, or enumeration int y = x::a; ^ ./test.cpp:2:8: note: 'x' declared here struct x; ^ 1 error generated. it is now: ./test.cpp:5:9: error: use of class template 'x' requires template arguments int y = x::a; ^ ./test.cpp:2:8: note: template is declared here struct x; ^ 1 error generated. Note that the call to `isTemplateName()` is basically copied from `DiagnoseUnknownTypeName()` in `SemaDecl.cpp`. However, just calling that from `SemaCXXScopeSpec.cpp` as well makes the `SemaObjCXX/property-dot-error.mm` test fail, because it now outputs clang/test/SemaObjCXX/propert-dot-error.mm Line 67: unknown type name 'D'; did you mean 'D'? clang/test/SemaObjCXX/propert-dot-error.mm Line 68: unknown type name 'D'; did you mean 'D'? and I don't know enough about objc to fix this, but if anyone has some pointers I'd be happy to avoid the code duplication. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D127638 Files: clang/lib/Sema/SemaCXXScopeSpec.cpp clang/test/SemaCXX/nested-name-spec.cpp Index: clang/test/SemaCXX/nested-name-spec.cpp =================================================================== --- clang/test/SemaCXX/nested-name-spec.cpp +++ clang/test/SemaCXX/nested-name-spec.cpp @@ -473,3 +473,10 @@ x: goto x; } } + +template <typename T> +struct x; // expected-note {{template is declared here}} + +template <typename T> +int issue55962 = x::a; // expected-error {{use of class template 'x' requires template arguments}} \ + // expected-warning {{variable templates are a C++14 extension}} Index: clang/lib/Sema/SemaCXXScopeSpec.cpp =================================================================== --- clang/lib/Sema/SemaCXXScopeSpec.cpp +++ clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -828,15 +828,30 @@ } if (!Found.empty()) { - if (TypeDecl *TD = Found.getAsSingle<TypeDecl>()) + if (TypeDecl *TD = Found.getAsSingle<TypeDecl>()) { Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) << Context.getTypeDeclType(TD) << getLangOpts().CPlusPlus; - else { - Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) - << IdInfo.Identifier << getLangOpts().CPlusPlus; - if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) - Diag(ND->getLocation(), diag::note_entity_declared_at) - << IdInfo.Identifier; + } else { + // Try to diagnose x::y where x is a class template and the + // template arguments are missing. + UnqualifiedId Name; + Name.setIdentifier(IdInfo.Identifier, IdInfo.IdentifierLoc); + CXXScopeSpec EmptySS; + TemplateTy TemplateResult; + bool MemberOfUnknownSpecialization; + if (isTemplateName(S, SS, /*hasTemplateKeyword=*/false, Name, nullptr, + true, TemplateResult, + MemberOfUnknownSpecialization) == TNK_Type_template) { + diagnoseMissingTemplateArguments(TemplateResult.get(), + IdInfo.IdentifierLoc); + } else { + Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) + << IdInfo.Identifier << getLangOpts().CPlusPlus; + if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) { + Diag(ND->getLocation(), diag::note_entity_declared_at) + << IdInfo.Identifier; + } + } } } else if (SS.isSet()) Diag(IdInfo.IdentifierLoc, diag::err_no_member) << IdInfo.Identifier
Index: clang/test/SemaCXX/nested-name-spec.cpp =================================================================== --- clang/test/SemaCXX/nested-name-spec.cpp +++ clang/test/SemaCXX/nested-name-spec.cpp @@ -473,3 +473,10 @@ x: goto x; } } + +template <typename T> +struct x; // expected-note {{template is declared here}} + +template <typename T> +int issue55962 = x::a; // expected-error {{use of class template 'x' requires template arguments}} \ + // expected-warning {{variable templates are a C++14 extension}} Index: clang/lib/Sema/SemaCXXScopeSpec.cpp =================================================================== --- clang/lib/Sema/SemaCXXScopeSpec.cpp +++ clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -828,15 +828,30 @@ } if (!Found.empty()) { - if (TypeDecl *TD = Found.getAsSingle<TypeDecl>()) + if (TypeDecl *TD = Found.getAsSingle<TypeDecl>()) { Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) << Context.getTypeDeclType(TD) << getLangOpts().CPlusPlus; - else { - Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) - << IdInfo.Identifier << getLangOpts().CPlusPlus; - if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) - Diag(ND->getLocation(), diag::note_entity_declared_at) - << IdInfo.Identifier; + } else { + // Try to diagnose x::y where x is a class template and the + // template arguments are missing. + UnqualifiedId Name; + Name.setIdentifier(IdInfo.Identifier, IdInfo.IdentifierLoc); + CXXScopeSpec EmptySS; + TemplateTy TemplateResult; + bool MemberOfUnknownSpecialization; + if (isTemplateName(S, SS, /*hasTemplateKeyword=*/false, Name, nullptr, + true, TemplateResult, + MemberOfUnknownSpecialization) == TNK_Type_template) { + diagnoseMissingTemplateArguments(TemplateResult.get(), + IdInfo.IdentifierLoc); + } else { + Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) + << IdInfo.Identifier << getLangOpts().CPlusPlus; + if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) { + Diag(ND->getLocation(), diag::note_entity_declared_at) + << IdInfo.Identifier; + } + } } } else if (SS.isSet()) Diag(IdInfo.IdentifierLoc, diag::err_no_member) << IdInfo.Identifier
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits