diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -158,6 +158,19 @@ } } +- By 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|? ============================== @@ -483,10 +496,9 @@ 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. 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. - 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 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1128,9 +1128,7 @@ // 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 @@ 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 @@ 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!"); @@ -5229,33 +5212,29 @@ // 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->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 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->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 FT2; + if (PackSize1 < PackSize2 && IsPackExpansion2) + return FT1; } } } @@ -5497,28 +5476,24 @@ if (Better1 && Better2) { // 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->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; - } + auto *TST1 = cast(T1); + auto *TST2 = cast(T2); + 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; } }