From 40e99473170f5045e0b5f2cafabd2a1be8c7ec26 Mon Sep 17 00:00:00 2001 From: Yuanfang Chen Date: Wed, 2 Nov 2022 11:54:19 -0700 Subject: [PATCH] [Clang] follow-up D128745, remove ClangABICompat checks Per discussions in D128745, remove ClangABICompat checks for implementations of DR692/DR1395/DR1432. This is a potentially breaking changes, so the release note is updated accordingly. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D136120 --- clang/docs/ReleaseNotes.rst | 23 +++- clang/lib/Sema/SemaTemplateDeduction.cpp | 157 +++++++++++--------------- clang/test/CodeGen/partial-order-variadic.cpp | 33 ------ clang/test/SemaCXX/pre-dr692.cpp | 14 --- 4 files changed, 85 insertions(+), 142 deletions(-) delete mode 100644 clang/test/CodeGen/partial-order-variadic.cpp delete mode 100644 clang/test/SemaCXX/pre-dr692.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 1198926..435d9de 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -161,6 +161,21 @@ code bases. - The ``-fexperimental-new-pass-manager`` and ``-fno-legacy-pass-manager`` flags have been removed. These have been no-ops since 15.0.0. +- As a side effect of implementing DR692/DR1395/DR1432, Clang now rejects some + overloaded function templates as ambiguous when one of the candidates has a + trailing parameter pack. + + .. code-block:: c++ + + template void g(T, T = T()); + template void g(T, U...); + void h() { + // This is rejected due to ambiguity between the pack and the + // default argument. Only parameters with arguments are considered during + // partial ordering of function templates. + g(42); + } + What's New in Clang |release|? ============================== Some of the major new features and improvements to Clang are listed @@ -551,10 +566,10 @@ C2x Feature Support C++ Language Changes in Clang ----------------------------- -- Implemented DR692, DR1395 and DR1432. Use the ``-fclang-abi-compat=15`` option - to get the old partial ordering behavior regarding packs. Note that the fix for - DR1432 is speculative that there is no wording or even resolution for this issue. - A speculative fix for DR1432 is needed because it fixes regressions caused by DR692. +- Implemented `DR692 `_, `DR1395 `_, + and `DR1432 `_. The fix for DR1432 is speculative since the + issue is still open and has no proposed resolution at this time. A speculative fix + for DR1432 is needed to prevent regressions that would otherwise occur due to DR692. - Clang's default C++/ObjC++ standard is now ``gnu++17`` instead of ``gnu++14``. This means Clang will by default accept code using features from C++17 and conforming GNU extensions. Projects incompatible with C++17 can add diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 17c0e2f..3db06a5 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1128,9 +1128,7 @@ DeduceTemplateArguments(Sema &S, // During partial ordering, if Ai was originally a function parameter pack: // - if P does not contain a function parameter type corresponding to Ai then // Ai is ignored; - bool ClangABICompat15 = S.Context.getLangOpts().getClangABICompat() <= - LangOptions::ClangABI::Ver15; - if (!ClangABICompat15 && PartialOrdering && ArgIdx + 1 == NumArgs && + if (PartialOrdering && ArgIdx + 1 == NumArgs && isa(Args[ArgIdx])) return Sema::TDK_Success; @@ -2466,9 +2464,6 @@ static bool isSameTemplateArg(ASTContext &Context, if (X.getKind() != Y.getKind()) return false; - bool ClangABICompat15 = - Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver15; - switch (X.getKind()) { case TemplateArgument::Null: llvm_unreachable("Comparing NULL template argument"); @@ -2500,45 +2495,33 @@ static bool isSameTemplateArg(ASTContext &Context, return XID == YID; } - case TemplateArgument::Pack: - if (ClangABICompat15) { - if (X.pack_size() != Y.pack_size()) + case TemplateArgument::Pack: { + unsigned PackIterationSize = X.pack_size(); + if (X.pack_size() != Y.pack_size()) { + if (!PartialOrdering) return false; - for (TemplateArgument::pack_iterator XP = X.pack_begin(), - XPEnd = X.pack_end(), - YP = Y.pack_begin(); - XP != XPEnd; ++XP, ++YP) - if (!isSameTemplateArg(Context, *XP, *YP, PartialOrdering, - PackExpansionMatchesPack)) - return false; - } else { - unsigned PackIterationSize = X.pack_size(); - if (X.pack_size() != Y.pack_size()) { - if (!PartialOrdering) - return false; - - // C++0x [temp.deduct.type]p9: - // During partial ordering, if Ai was originally a pack expansion: - // - if P does not contain a template argument corresponding to Ai - // then Ai is ignored; - bool XHasMoreArg = X.pack_size() > Y.pack_size(); - if (!(XHasMoreArg && X.pack_elements().back().isPackExpansion()) && - !(!XHasMoreArg && Y.pack_elements().back().isPackExpansion())) - return false; - - if (XHasMoreArg) - PackIterationSize = Y.pack_size(); - } + // C++0x [temp.deduct.type]p9: + // During partial ordering, if Ai was originally a pack expansion: + // - if P does not contain a template argument corresponding to Ai + // then Ai is ignored; + bool XHasMoreArg = X.pack_size() > Y.pack_size(); + if (!(XHasMoreArg && X.pack_elements().back().isPackExpansion()) && + !(!XHasMoreArg && Y.pack_elements().back().isPackExpansion())) + return false; - ArrayRef XP = X.pack_elements(); - ArrayRef YP = Y.pack_elements(); - for (unsigned i = 0; i < PackIterationSize; ++i) - if (!isSameTemplateArg(Context, XP[i], YP[i], PartialOrdering, - PackExpansionMatchesPack)) - return false; + if (XHasMoreArg) + PackIterationSize = Y.pack_size(); } + + ArrayRef XP = X.pack_elements(); + ArrayRef YP = Y.pack_elements(); + for (unsigned i = 0; i < PackIterationSize; ++i) + if (!isSameTemplateArg(Context, XP[i], YP[i], PartialOrdering, + PackExpansionMatchesPack)) + return false; return true; + } } llvm_unreachable("Invalid TemplateArgument Kind!"); @@ -5245,34 +5228,30 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate( // This a speculative fix for CWG1432 (Similar to the fix for CWG1395) that // there is no wording or even resolution for this issue. - 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().getCanonicalType(); - QualType T2 = FD2->getParamDecl(i)->getType().getCanonicalType(); - auto *TST1 = dyn_cast(T1); - auto *TST2 = dyn_cast(T2); - if (!TST1 || !TST2) - continue; - const TemplateArgument &TA1 = TST1->template_arguments().back(); - if (TA1.getKind() == TemplateArgument::Pack) { - assert(TST1->template_arguments().size() == - TST2->template_arguments().size()); - 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 FT2; - if (PackSize1 < PackSize2 && IsPackExpansion2) - return FT1; - } + for (int i = 0, e = std::min(NumParams1, NumParams2); i < e; ++i) { + QualType T1 = FD1->getParamDecl(i)->getType().getCanonicalType(); + QualType T2 = FD2->getParamDecl(i)->getType().getCanonicalType(); + auto *TST1 = dyn_cast(T1); + auto *TST2 = dyn_cast(T2); + if (!TST1 || !TST2) + continue; + const TemplateArgument &TA1 = TST1->template_arguments().back(); + if (TA1.getKind() == TemplateArgument::Pack) { + assert(TST1->template_arguments().size() == + TST2->template_arguments().size()); + 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 FT2; + if (PackSize1 < PackSize2 && IsPackExpansion2) + return FT1; } } } @@ -5618,29 +5597,25 @@ getMoreSpecialized(Sema &S, QualType T1, QualType T2, TemplateLikeDecl *P1, // This a speculative fix for CWG1432 (Similar to the fix for CWG1395) that // there is no wording or even resolution for this issue. - bool ClangABICompat15 = S.Context.getLangOpts().getClangABICompat() <= - LangOptions::ClangABI::Ver15; - if (!ClangABICompat15) { - auto *TST1 = cast(T1); - auto *TST2 = cast(T2); - const TemplateArgument &TA1 = TST1->template_arguments().back(); - if (TA1.getKind() == TemplateArgument::Pack) { - assert(TST1->template_arguments().size() == - TST2->template_arguments().size()); - 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; - } + auto *TST1 = cast(T1); + auto *TST2 = cast(T2); + const TemplateArgument &TA1 = TST1->template_arguments().back(); + if (TA1.getKind() == TemplateArgument::Pack) { + assert(TST1->template_arguments().size() == + TST2->template_arguments().size()); + 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; } } diff --git a/clang/test/CodeGen/partial-order-variadic.cpp b/clang/test/CodeGen/partial-order-variadic.cpp deleted file mode 100644 index a10cd68..0000000 --- a/clang/test/CodeGen/partial-order-variadic.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15 %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,AFTER-15 - -// CHECK: %struct.S = type { i8 } -// CHECK: @_Z2ggiRi -// CHECK: @_Z1gIiJEERiPT_DpT0_ -template int &g(T *, U...); -template void g(T); -template struct S; -template struct S {}; -void gg(int i, int &r) { - r = g(&i); - S a; -} - -// CHECK: @_Z1hIJiEEvDpPT_ -template void h(T*...) {} -template void h(const T&) {} -template void h(int*); - -#if !defined(CLANG_ABI_COMPAT) - -// AFTER-15: @_Z1fIiJEEvPT_DpT0_ -template void f(T*, U...){} -template void f(T){} -template void f(int*); - -template struct A; -template struct A {}; -template struct A; -template struct A; - -#endif diff --git a/clang/test/SemaCXX/pre-dr692.cpp b/clang/test/SemaCXX/pre-dr692.cpp deleted file mode 100644 index 87eac31..0000000 --- a/clang/test/SemaCXX/pre-dr692.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// RUN: %clang_cc1 %s -std=c++11 -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -fclang-abi-compat=15 - -template struct A1 {}; -template struct A2 {}; -template void e1(A1); // expected-note {{candidate}} -template void e1(A1); // expected-note {{candidate}} -template void e2(A2); // expected-note {{candidate}} -template void e2(A2); // expected-note {{candidate}} -void h() { - A1 b1; - e1(b1); // expected-error{{call to 'e1' is ambiguous}} - A2 b2; - e2(b2); // expected-error{{call to 'e2' is ambiguous}} -} -- 2.7.4