Author: rsmith Date: Tue Jul 31 14:01:53 2018 New Revision: 338438 URL: http://llvm.org/viewvc/llvm-project?rev=338438&view=rev Log: [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! Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/test/PCH/cxx-templates.cpp cfe/trunk/test/PCH/cxx-templates.h Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=338438&r1=338437&r2=338438&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Jul 31 14:01:53 2018 @@ -3439,22 +3439,16 @@ static void inheritDefaultTemplateArgume 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); } } Modified: cfe/trunk/test/PCH/cxx-templates.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-templates.cpp?rev=338438&r1=338437&r2=338438&view=diff ============================================================================== --- cfe/trunk/test/PCH/cxx-templates.cpp (original) +++ cfe/trunk/test/PCH/cxx-templates.cpp Tue Jul 31 14:01:53 2018 @@ -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 Modified: cfe/trunk/test/PCH/cxx-templates.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-templates.h?rev=338438&r1=338437&r2=338438&view=diff ============================================================================== --- cfe/trunk/test/PCH/cxx-templates.h (original) +++ cfe/trunk/test/PCH/cxx-templates.h Tue Jul 31 14:01:53 2018 @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits