return FT1;
}
+ // 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<TemplateSpecializationType>(T1);
+ auto *TST2 = dyn_cast<TemplateSpecializationType>(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;
+ }
+ }
+ }
+ }
+
return JudgeByConstraints();
}
return nullptr;
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) {
- // 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;
- }
+ auto *TST1 = cast<TemplateSpecializationType>(T1);
+ auto *TST2 = cast<TemplateSpecializationType>(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;
}
}
}
// 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 U> int &f(U, A<U, U> *p = 0); // expected-note {{candidate}}
+ template <typename... T> struct A1 {}; // expected-error 0-1{{C++11}}
+ template <typename U, typename... T> struct A2 {}; // expected-error 0-1{{C++11}}
+ template <class T1, class... U> void e1(A1<T1, U...>) = delete; // expected-error 0-2{{C++11}}
+ template <class T1> void e1(A1<T1>);
+ template <class T1, class... U> void e2(A2<T1, U...>) = delete; // expected-error 0-2{{C++11}}
+ template <class T1> void e2(A2<T1>);
+ template <typename T, typename U> void f(U, A1<U, T> *p = 0) = delete; // expected-note {{candidate}} expected-error 0-1{{C++11}}
+ template <typename U> int &f(U, A1<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);
+ A1<int, int> a;
+ int &r = f<int>(42, &a);
+ A1<int> b1;
+ e1(b1);
+ A2<int> b2;
+ e2(b2);
f<int>(42); // expected-error {{ambiguous}}
g(42); // expected-error {{ambiguous}}
}