Author: Sheng Date: 2023-05-24T21:46:31+08:00 New Revision: cde139016a4eb2d71950e135f9c037987ecdb7cf
URL: https://github.com/llvm/llvm-project/commit/cde139016a4eb2d71950e135f9c037987ecdb7cf DIFF: https://github.com/llvm/llvm-project/commit/cde139016a4eb2d71950e135f9c037987ecdb7cf.diff LOG: [clang][Sema] Fix a crash when instantiating a non-type template argument in a dependent scope. The type alias template is not diagnosed when instantiating an expected non-type template argument in a dependent scope, causing ICE. Besides that, the diagnostic message has been updated to account for the fact that the function template is not the only non-type template. Fixes #62533 Reviewed By: #clang-language-wg, erichkeane Differential Revision: https://reviews.llvm.org/D151062 Added: clang/test/SemaCXX/PR62533.cpp Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaTemplate.cpp clang/test/SemaTemplate/ms-sizeof-missing-typename.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 92fe909e5e8a6..38a1347368c4c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -437,7 +437,8 @@ Bug Fixes in This Version ``__builtin_dynamic_object_size`` on structs containing flexible array members. (`#62789 <https://github.com/llvm/llvm-project/issues/62789>`_). - +- Fix a crash when instantiating a non-type template argument in a dependent scope. + (`#62533 <https://github.com/llvm/llvm-project/issues/62533>`_). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d21cb62cd0423..0cbc2fc8c8949 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5490,10 +5490,10 @@ def note_template_kw_refers_to_non_template : Note< def err_template_kw_refers_to_dependent_non_template : Error< "%0%select{| following the 'template' keyword}1 " "cannot refer to a dependent template">; -def err_template_kw_refers_to_class_template : Error< - "'%0%1' instantiated to a class template, not a function template">; -def note_referenced_class_template : Note< - "class template declared here">; +def err_template_kw_refers_to_type_template : Error< + "'%0%1' is expected to be a non-type template, but instantiated to a %select{class|type alias}2 template">; +def note_referenced_type_template : Note< + "%select{class|type alias}0 template declared here">; def err_template_kw_missing : Error< "missing 'template' keyword prior to dependent template name '%0%1'">; def ext_template_outside_of_template : ExtWarn< diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 7a545214596ba..063ddb418c431 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5001,13 +5001,20 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, return ExprError(); } - if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) { - Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_class_template) - << SS.getScopeRep() - << NameInfo.getName().getAsString() << SS.getRange(); - Diag(Temp->getLocation(), diag::note_referenced_class_template); + auto DiagnoseTypeTemplateDecl = [&](TemplateDecl *Temp, + bool isTypeAliasTemplateDecl) { + Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_type_template) + << SS.getScopeRep() << NameInfo.getName().getAsString() << SS.getRange() + << isTypeAliasTemplateDecl; + Diag(Temp->getLocation(), diag::note_referenced_type_template) << 0; return ExprError(); - } + }; + + if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) + return DiagnoseTypeTemplateDecl(Temp, false); + + if (TypeAliasTemplateDecl *Temp = R.getAsSingle<TypeAliasTemplateDecl>()) + return DiagnoseTypeTemplateDecl(Temp, true); return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs); } diff --git a/clang/test/SemaCXX/PR62533.cpp b/clang/test/SemaCXX/PR62533.cpp new file mode 100644 index 0000000000000..920ea54d4b00e --- /dev/null +++ b/clang/test/SemaCXX/PR62533.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct test { + template<typename> using fun_ diff = char; // expected-note 2{{class template declared here}} +}; + +template<typename T, typename V> +decltype(T::template fun_ diff <V>) foo1() {} +// expected-note@-1 {{candidate template ignored: substitution failure [with T = test<int>, V = int]: 'test<int>::fun_ diff ' is expected to be a non-type template, but instantiated to a type alias template}} + +template<typename T> +void foo2() { + // expected-error@+1 {{test<int>::fun_ diff ' is expected to be a non-type template, but instantiated to a type alias template}} + int a = test<T>::template fun_ diff <int>; +} + +template<typename T, typename V> +struct has_fun_ diff { + using type = double; +}; + +template<typename T> +struct has_fun_ diff <T, int> { + // expected-error@+1 {{'test<int>::fun_ diff ' is expected to be a non-type template, but instantiated to a type alias template}} + using type = decltype(T::template fun_ diff <int>); +}; + +void bar() { + foo1<test<int>, int>(); // expected-error {{no matching function for call to 'foo1'}} + foo2<int>(); // expected-note {{in instantiation of function template specialization}} + has_fun_ diff <test<int>, int>::type a; // expected-note {{in instantiation of template class}} +} diff --git a/clang/test/SemaTemplate/ms-sizeof-missing-typename.cpp b/clang/test/SemaTemplate/ms-sizeof-missing-typename.cpp index 9bafe6c98c2b7..fcba385be5ab4 100644 --- a/clang/test/SemaTemplate/ms-sizeof-missing-typename.cpp +++ b/clang/test/SemaTemplate/ms-sizeof-missing-typename.cpp @@ -50,7 +50,7 @@ template struct Foo<Bar>; // expected-note-re {{in instantiation {{.*}} requeste } namespace ambiguous_missing_parens { -// expected-error@+1 {{'Q::U' instantiated to a class template, not a function template}} +// expected-error@+1 {{'Q::U' is expected to be a non-type template, but instantiated to a class template}} template <typename T> void f() { int a = sizeof T::template U<0> + 4; } struct Q { // expected-note@+1 {{class template declared here}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits