Author: epilk Date: Tue Jun 28 18:05:09 2016 New Revision: 274077 URL: http://llvm.org/viewvc/llvm-project?rev=274077&view=rev Log: [Sema] Disallow ambigious base classes in template argument deduction
Fixes PR28195. Differential revision: http://reviews.llvm.org/D21653 Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=274077&r1=274076&r2=274077&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Jun 28 18:05:09 2016 @@ -103,12 +103,12 @@ DeduceTemplateArgumentsByTypeMatch(Sema bool PartialOrdering = false); static Sema::TemplateDeductionResult -DeduceTemplateArguments(Sema &S, - TemplateParameterList *TemplateParams, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, const TemplateArgument *Params, unsigned NumParams, const TemplateArgument *Args, unsigned NumArgs, TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced); + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + bool NumberOfArgumentsMustMatch); /// \brief If the given expression is of a form that permits the deduction /// of a non-type template parameter, return the declaration of that @@ -453,10 +453,10 @@ DeduceTemplateArguments(Sema &S, // Perform template argument deduction on each template // argument. Ignore any missing/extra arguments, since they could be // filled in by default arguments. - return DeduceTemplateArguments(S, TemplateParams, - Param->getArgs(), Param->getNumArgs(), - SpecArg->getArgs(), SpecArg->getNumArgs(), - Info, Deduced); + return DeduceTemplateArguments(S, TemplateParams, Param->getArgs(), + Param->getNumArgs(), SpecArg->getArgs(), + SpecArg->getNumArgs(), Info, Deduced, + /*NumberOfArgumentsMustMatch=*/false); } // If the argument type is a class template specialization, we @@ -487,11 +487,10 @@ DeduceTemplateArguments(Sema &S, return Result; // Perform template argument deduction for the template arguments. - return DeduceTemplateArguments(S, TemplateParams, - Param->getArgs(), Param->getNumArgs(), - SpecArg->getTemplateArgs().data(), - SpecArg->getTemplateArgs().size(), - Info, Deduced); + return DeduceTemplateArguments( + S, TemplateParams, Param->getArgs(), Param->getNumArgs(), + SpecArg->getTemplateArgs().data(), SpecArg->getTemplateArgs().size(), + Info, Deduced, /*NumberOfArgumentsMustMatch=*/true); } /// \brief Determines whether the given type is an opaque type that @@ -1461,6 +1460,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema SmallVector<const RecordType *, 8> ToVisit; ToVisit.push_back(RecordT); bool Successful = false; + SmallVector<DeducedTemplateArgument, 8> SuccessfulDeduced; while (!ToVisit.empty()) { // Retrieve the next class in the inheritance hierarchy. const RecordType *NextT = ToVisit.pop_back_val(); @@ -1481,14 +1481,20 @@ DeduceTemplateArgumentsByTypeMatch(Sema // note that we had some success. Otherwise, ignore any deductions // from this base class. if (BaseResult == Sema::TDK_Success) { + // If we've already seen some success, then deduction fails due to + // an ambiguity (temp.deduct.call p5). + if (Successful) + return Sema::TDK_MiscellaneousDeductionFailure; + Successful = true; - DeducedOrig.clear(); - DeducedOrig.append(Deduced.begin(), Deduced.end()); + std::swap(SuccessfulDeduced, Deduced); + Info.Param = BaseInfo.Param; Info.FirstArg = BaseInfo.FirstArg; Info.SecondArg = BaseInfo.SecondArg; - } else - Deduced = DeducedOrig; + } + + Deduced = DeducedOrig; } // Visit base classes @@ -1500,8 +1506,10 @@ DeduceTemplateArgumentsByTypeMatch(Sema } } - if (Successful) + if (Successful) { + std::swap(SuccessfulDeduced, Deduced); return Sema::TDK_Success; + } return Result; } @@ -1825,12 +1833,12 @@ static bool hasPackExpansionBeforeEnd(co } static Sema::TemplateDeductionResult -DeduceTemplateArguments(Sema &S, - TemplateParameterList *TemplateParams, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, const TemplateArgument *Params, unsigned NumParams, const TemplateArgument *Args, unsigned NumArgs, TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + bool NumberOfArgumentsMustMatch) { // C++0x [temp.deduct.type]p9: // If the template argument list of P contains a pack expansion that is not // the last template argument, the entire template argument list is a @@ -1850,7 +1858,8 @@ DeduceTemplateArguments(Sema &S, // Check whether we have enough arguments. if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) - return Sema::TDK_Success; + return NumberOfArgumentsMustMatch ? Sema::TDK_TooFewArguments + : Sema::TDK_Success; if (Args[ArgIdx].isPackExpansion()) { // FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here, @@ -1921,7 +1930,7 @@ DeduceTemplateArguments(Sema &S, return DeduceTemplateArguments(S, TemplateParams, ParamList.data(), ParamList.size(), ArgList.data(), ArgList.size(), - Info, Deduced); + Info, Deduced, false); } /// \brief Determine whether two template arguments are the same. Modified: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp?rev=274077&r1=274076&r2=274077&view=diff ============================================================================== --- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp (original) +++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp Tue Jun 28 18:05:09 2016 @@ -160,3 +160,16 @@ int fn() { } } + +namespace PR28195 { + +template<int N> struct B {}; +struct D : B<0>, B<1> {}; + +template<int N> int callee(B<N>); // expected-note{{failed template argument deduction}} + +int caller() { + callee(D()); // expected-error{{no matching function}} +} + +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits