From 87d263e870752d1bd724183bd88be47f6d2f6fed Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sun, 25 Dec 2016 08:05:23 +0000 Subject: Fix some subtle wrong partial ordering bugs particularly with C++1z auto-typed non-type template parameters. During partial ordering, when checking the substituted deduced template arguments match the original, check the types of non-type template arguments match even if they're dependent. The only way we get dependent types here is if they really represent types of the other template (which are supposed to be modeled as being substituted for unique, non-dependent types). In order to make this work for auto-typed non-type template arguments, we need to be able to perform auto deduction even when the initializer and (potentially) the auto type are dependent, support for which is the bulk of this patch. (Note that this requires the ability to deduce only a single level of a multi-level dependent type.) llvm-svn: 290511 --- clang/lib/Sema/SemaTemplate.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'clang/lib/Sema/SemaTemplate.cpp') diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index bbf1965eef4..766ed944b13 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5008,9 +5008,15 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // If the parameter type somehow involves auto, deduce the type now. if (getLangOpts().CPlusPlus1z && ParamType->isUndeducedType()) { + // When checking a deduced template argument, deduce from its type even if + // the type is dependent, in order to check the types of non-type template + // arguments line up properly in partial ordering. + Optional Depth; + if (CTAK != CTAK_Specified) + Depth = Param->getDepth() + 1; if (DeduceAutoType( Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation()), - Arg, ParamType) == DAR_Failed) { + Arg, ParamType, Depth) == DAR_Failed) { Diag(Arg->getExprLoc(), diag::err_non_type_template_parm_type_deduction_failure) << Param->getDeclName() << Param->getType() << Arg->getType() @@ -5029,14 +5035,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } } - // If either the parameter has a dependent type or the argument is - // type-dependent, there's nothing we can check now. - if (ParamType->isDependentType() || Arg->isTypeDependent()) { - // FIXME: Produce a cloned, canonical expression? - Converted = TemplateArgument(Arg); - return Arg; - } - // We should have already dropped all cv-qualifiers by now. assert(!ParamType.hasQualifiers() && "non-type template parameter type cannot be qualified"); @@ -5058,6 +5056,14 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return ExprError(); } + // If either the parameter has a dependent type or the argument is + // type-dependent, there's nothing we can check now. + if (ParamType->isDependentType() || Arg->isTypeDependent()) { + // FIXME: Produce a cloned, canonical expression? + Converted = TemplateArgument(Arg); + return Arg; + } + if (getLangOpts().CPlusPlus1z) { // C++1z [temp.arg.nontype]p1: // A template-argument for a non-type template parameter shall be -- cgit v1.2.3