From: Richard Smith Date: Tue, 31 Jul 2018 21:01:53 +0000 (+0000) Subject: [serialization] PR34728: Don't assume that only a suffix of template X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=84fd36a067fc9b9529d42ff596b22fff8a607a28;p=clang [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! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338438 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index da30612b4f..ad37a2978d 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -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(FromParam)) { - if (!inheritDefaultTemplateArgument(Context, FTTP, ToParam)) - break; - } else if (auto *FNTTP = dyn_cast(FromParam)) { - if (!inheritDefaultTemplateArgument(Context, FNTTP, ToParam)) - break; - } else { - if (!inheritDefaultTemplateArgument( - Context, cast(FromParam), ToParam)) - break; - } + if (auto *FTTP = dyn_cast(FromParam)) + inheritDefaultTemplateArgument(Context, FTTP, ToParam); + else if (auto *FNTTP = dyn_cast(FromParam)) + inheritDefaultTemplateArgument(Context, FNTTP, ToParam); + else + inheritDefaultTemplateArgument( + Context, cast(FromParam), ToParam); } } diff --git a/test/PCH/cxx-templates.cpp b/test/PCH/cxx-templates.cpp index e241701f50..a7f7b1981f 100644 --- a/test/PCH/cxx-templates.cpp +++ b/test/PCH/cxx-templates.cpp @@ -116,3 +116,19 @@ namespace MemberSpecializationLocation { #endif int k = A::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 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 diff --git a/test/PCH/cxx-templates.h b/test/PCH/cxx-templates.h index 68b252e797..e812aa68fb 100644 --- a/test/PCH/cxx-templates.h +++ b/test/PCH/cxx-templates.h @@ -361,3 +361,38 @@ namespace rdar15468709c { namespace MemberSpecializationLocation { template 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 func1(T const &); + +template +int func1(T const &) { + return foo; +} + +// case 2: defaulted `TemplateTypeParmDecl`, non-defaulted 2nd tpl param +template +A func2(B const &); + +template +A func2(B const &) { + return A(20.0f); +} + +// case 3: defaulted `TemplateTemplateParmDecl`, non-defaulted 2nd tpl param +template +struct Container { T const &item; }; + +template