forked from OSchip/llvm-project
[serialization] PR34728: Don't assume that only a suffix of template
parameters can have default arguments. At least for function templates and class template partial specializations, it's possible for a template parameter with a default argument to be followed by a non-pack template parameter with no default argument, and this case was not properly handled here. Testcase by Steve O'Brien! llvm-svn: 338438
This commit is contained in:
parent
baf94f830b
commit
559cc69789
|
@ -3439,22 +3439,16 @@ static void inheritDefaultTemplateArguments(ASTContext &Context,
|
|||
assert(FromTP->size() == ToTP->size() && "merged mismatched templates?");
|
||||
|
||||
for (unsigned I = 0, N = FromTP->size(); I != N; ++I) {
|
||||
NamedDecl *FromParam = FromTP->getParam(N - I - 1);
|
||||
if (FromParam->isParameterPack())
|
||||
continue;
|
||||
NamedDecl *ToParam = ToTP->getParam(N - I - 1);
|
||||
NamedDecl *FromParam = FromTP->getParam(I);
|
||||
NamedDecl *ToParam = ToTP->getParam(I);
|
||||
|
||||
if (auto *FTTP = dyn_cast<TemplateTypeParmDecl>(FromParam)) {
|
||||
if (!inheritDefaultTemplateArgument(Context, FTTP, ToParam))
|
||||
break;
|
||||
} else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam)) {
|
||||
if (!inheritDefaultTemplateArgument(Context, FNTTP, ToParam))
|
||||
break;
|
||||
} else {
|
||||
if (!inheritDefaultTemplateArgument(
|
||||
Context, cast<TemplateTemplateParmDecl>(FromParam), ToParam))
|
||||
break;
|
||||
}
|
||||
if (auto *FTTP = dyn_cast<TemplateTypeParmDecl>(FromParam))
|
||||
inheritDefaultTemplateArgument(Context, FTTP, ToParam);
|
||||
else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam))
|
||||
inheritDefaultTemplateArgument(Context, FNTTP, ToParam);
|
||||
else
|
||||
inheritDefaultTemplateArgument(
|
||||
Context, cast<TemplateTemplateParmDecl>(FromParam), ToParam);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -116,3 +116,19 @@ namespace MemberSpecializationLocation {
|
|||
#endif
|
||||
int k = A<int>::n;
|
||||
}
|
||||
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=34728
|
||||
namespace PR34728 {
|
||||
int test() {
|
||||
// Verify with several TemplateParmDecl kinds, using PCH (incl. modules).
|
||||
int z1 = func1(/*ignored*/2.718);
|
||||
int z2 = func2(/*ignored*/3.142);
|
||||
int tmp3 = 30;
|
||||
Container<int> c = func3(tmp3);
|
||||
int z3 = c.item;
|
||||
|
||||
// Return value is meaningless. Just "use" all these values to avoid
|
||||
// warning about unused vars / values.
|
||||
return z1 + z2 + z3;
|
||||
}
|
||||
} // end namespace PR34728
|
||||
|
|
|
@ -361,3 +361,38 @@ namespace rdar15468709c {
|
|||
namespace MemberSpecializationLocation {
|
||||
template<typename T> struct A { static int n; };
|
||||
}
|
||||
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=34728
|
||||
namespace PR34728 {
|
||||
|
||||
// case 1: defaulted `NonTypeTemplateParmDecl`, non-defaulted 2nd tpl param
|
||||
template <int foo = 10, class T>
|
||||
int func1(T const &);
|
||||
|
||||
template <int foo, class T>
|
||||
int func1(T const &) {
|
||||
return foo;
|
||||
}
|
||||
|
||||
// case 2: defaulted `TemplateTypeParmDecl`, non-defaulted 2nd tpl param
|
||||
template <class A = int, class B>
|
||||
A func2(B const &);
|
||||
|
||||
template <class A, class B>
|
||||
A func2(B const &) {
|
||||
return A(20.0f);
|
||||
}
|
||||
|
||||
// case 3: defaulted `TemplateTemplateParmDecl`, non-defaulted 2nd tpl param
|
||||
template <class T>
|
||||
struct Container { T const &item; };
|
||||
|
||||
template <template <class> class C = Container, class D>
|
||||
C<D> func3(D const &);
|
||||
|
||||
template <template <class> class C, class D>
|
||||
C<D> func3(D const &d) {
|
||||
return Container<D>{d};
|
||||
}
|
||||
|
||||
} // end namespace PR34728
|
||||
|
|
Loading…
Reference in New Issue