diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/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(T1); + auto *TST2 = dyn_cast(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(); auto *TST2 = T2->castAs(); - 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; } } diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp --- a/clang/test/CXX/drs/dr6xx.cpp +++ b/clang/test/CXX/drs/dr6xx.cpp @@ -1083,13 +1083,18 @@ // Also see dr1395. namespace temp_func_order_example2 { - template struct A {}; - template void f(U, A *p = 0); // expected-note {{candidate}} + template struct A {}; // expected-error 0-1{{C++11}} + template void e(A) = delete; // expected-error 0-2{{C++11}} + template void e(A); + template void f(U, A *p = 0) = delete; // expected-note {{candidate}} expected-error 0-1{{C++11}} template int &f(U, A *p = 0); // expected-note {{candidate}} template void g(T, T = T()); // expected-note {{candidate}} template void g(T, U...); // expected-note {{candidate}} expected-error 0-1{{C++11}} void h() { - int &r = f(42, (A *)0); + A a; + int &r = f(42, &a); + A b; + e(b); f(42); // expected-error {{ambiguous}} g(42); // expected-error {{ambiguous}} }