ychen created this revision. ychen added reviewers: aaron.ballman, erichkeane. Herald added a project: All. ychen requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
D128745 <https://reviews.llvm.org/D128745> handled DR1432 for the partial ordering of partial specializations, but missed the handling for the partial ordering of function templates. This patch implements the latter. While at it, also simplies the previous implementation to be more close the wording without funtional changes. Fixes https://github.com/llvm/llvm-project/issues/56090 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D133683 Files: clang/lib/Sema/SemaTemplateDeduction.cpp clang/test/CXX/drs/dr6xx.cpp
Index: clang/test/CXX/drs/dr6xx.cpp =================================================================== --- clang/test/CXX/drs/dr6xx.cpp +++ clang/test/CXX/drs/dr6xx.cpp @@ -1083,13 +1083,18 @@ // Also see dr1395. namespace temp_func_order_example2 { - template <typename T, typename U> struct A {}; - template <typename T, typename U> void f(U, A<U, T> *p = 0); // expected-note {{candidate}} + template <typename... T> struct A {}; // expected-error 0-1{{C++11}} + template <class T1, class... U> void e(A<T1, U...>) = delete; // expected-error 0-2{{C++11}} + template <class T1> void e(A<T1>); + template <typename T, typename U> void f(U, A<U, T> *p = 0) = delete; // expected-note {{candidate}} expected-error 0-1{{C++11}} template <typename U> int &f(U, A<U, U> *p = 0); // expected-note {{candidate}} template <typename T> void g(T, T = T()); // expected-note {{candidate}} template <typename T, typename... U> void g(T, U...); // expected-note {{candidate}} expected-error 0-1{{C++11}} void h() { - int &r = f<int>(42, (A<int, int> *)0); + A<int, int> a; + int &r = f<int>(42, &a); + A<int> b; + e(b); f<int>(42); // expected-error {{ambiguous}} g(42); // expected-error {{ambiguous}} } Index: clang/lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- clang/lib/Sema/SemaTemplateDeduction.cpp +++ clang/lib/Sema/SemaTemplateDeduction.cpp @@ -5187,6 +5187,32 @@ return FT1; } + // Consider this a fix for CWG1432. Similar to the fix for CWG1395. + bool ClangABICompat15 = + Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver15; + if (!ClangABICompat15) { + for (int i = 0, e = std::min(NumParams1, NumParams2); i < e; ++i) { + QualType T1 = FD1->getParamDecl(i)->getType().getDesugaredType(Context); + QualType T2 = FD2->getParamDecl(i)->getType().getDesugaredType(Context); + auto *TST1 = dyn_cast<TemplateSpecializationType>(T1); + auto *TST2 = dyn_cast<TemplateSpecializationType>(T2); + if (TST1 && TST2) { + unsigned NumArgs1 = TST1->getNumArgs(); + unsigned NumArgs2 = TST2->getNumArgs(); + bool IsPackExpansion1 = + NumArgs1 && TST1->template_arguments().back().isPackExpansion(); + bool IsPackExpansion2 = + NumArgs2 && TST2->template_arguments().back().isPackExpansion(); + if (NumArgs1 != NumArgs2 && IsPackExpansion1 != IsPackExpansion2) { + if (NumArgs1 > NumArgs2 && IsPackExpansion1) + return FT2; + if (NumArgs1 < NumArgs2 && IsPackExpansion2) + return FT1; + } + } + } + } + return JudgeByConstraints(); } @@ -5422,31 +5448,29 @@ return nullptr; if (Better1 && Better2) { + // Consider this a fix for CWG1432. Similar to the fix for CWG1395. bool ClangABICompat15 = S.Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver15; if (!ClangABICompat15) { - // Consider this a fix for CWG1432. Similar to the fix for CWG1395. auto *TST1 = T1->castAs<TemplateSpecializationType>(); auto *TST2 = T2->castAs<TemplateSpecializationType>(); - if (TST1->getNumArgs()) { - const TemplateArgument &TA1 = TST1->template_arguments().back(); - if (TA1.getKind() == TemplateArgument::Pack) { - assert(TST1->getNumArgs() == TST2->getNumArgs()); - const TemplateArgument &TA2 = TST2->template_arguments().back(); - assert(TA2.getKind() == TemplateArgument::Pack); - unsigned PackSize1 = TA1.pack_size(); - unsigned PackSize2 = TA2.pack_size(); - bool IsPackExpansion1 = - PackSize1 && TA1.pack_elements().back().isPackExpansion(); - bool IsPackExpansion2 = - PackSize2 && TA2.pack_elements().back().isPackExpansion(); - if (PackSize1 != PackSize2 && IsPackExpansion1 != IsPackExpansion2) { - if (PackSize1 > PackSize2 && IsPackExpansion1) - return GetP2()(P1, P2); - if (PackSize1 < PackSize2 && IsPackExpansion2) - return P1; - } - } + const TemplateArgument &TA1 = TST1->template_arguments().back(); + const TemplateArgument &TA2 = TST2->template_arguments().back(); + unsigned PackSize1 = + TA1.getKind() == TemplateArgument::Pack ? TA1.pack_size() : 0u; + unsigned PackSize2 = + TA2.getKind() == TemplateArgument::Pack ? TA2.pack_size() : 0u; + bool IsPackExpansion1 = + PackSize1 && TA1.pack_elements().back().isPackExpansion(); + bool IsPackExpansion2 = + PackSize2 && TA2.pack_elements().back().isPackExpansion(); + unsigned NumArgs1 = TST1->getNumArgs() + PackSize1; + unsigned NumArgs2 = TST2->getNumArgs() + PackSize2; + if (NumArgs1 != NumArgs2 && IsPackExpansion1 != IsPackExpansion2) { + if (NumArgs1 > NumArgs2 && IsPackExpansion1) + return GetP2()(P1, P2); + if (NumArgs1 < NumArgs2 && IsPackExpansion2) + return P1; } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits