Skip to content

Commit 6a16ac0

Browse files
committedJun 28, 2016
[Sema] Disallow ambigious base classes in template argument deduction
Fixes PR28195. Differential revision: http://reviews.llvm.org/D21653 llvm-svn: 274077
1 parent 2b2b1a9 commit 6a16ac0

File tree

2 files changed

+44
-22
lines changed

2 files changed

+44
-22
lines changed
 

‎clang/lib/Sema/SemaTemplateDeduction.cpp

+31-22
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,12 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
103103
bool PartialOrdering = false);
104104

105105
static Sema::TemplateDeductionResult
106-
DeduceTemplateArguments(Sema &S,
107-
TemplateParameterList *TemplateParams,
106+
DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
108107
const TemplateArgument *Params, unsigned NumParams,
109108
const TemplateArgument *Args, unsigned NumArgs,
110109
TemplateDeductionInfo &Info,
111-
SmallVectorImpl<DeducedTemplateArgument> &Deduced);
110+
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
111+
bool NumberOfArgumentsMustMatch);
112112

113113
/// \brief If the given expression is of a form that permits the deduction
114114
/// of a non-type template parameter, return the declaration of that
@@ -453,10 +453,10 @@ DeduceTemplateArguments(Sema &S,
453453
// Perform template argument deduction on each template
454454
// argument. Ignore any missing/extra arguments, since they could be
455455
// filled in by default arguments.
456-
return DeduceTemplateArguments(S, TemplateParams,
457-
Param->getArgs(), Param->getNumArgs(),
458-
SpecArg->getArgs(), SpecArg->getNumArgs(),
459-
Info, Deduced);
456+
return DeduceTemplateArguments(S, TemplateParams, Param->getArgs(),
457+
Param->getNumArgs(), SpecArg->getArgs(),
458+
SpecArg->getNumArgs(), Info, Deduced,
459+
/*NumberOfArgumentsMustMatch=*/false);
460460
}
461461

462462
// If the argument type is a class template specialization, we
@@ -487,11 +487,10 @@ DeduceTemplateArguments(Sema &S,
487487
return Result;
488488

489489
// Perform template argument deduction for the template arguments.
490-
return DeduceTemplateArguments(S, TemplateParams,
491-
Param->getArgs(), Param->getNumArgs(),
492-
SpecArg->getTemplateArgs().data(),
493-
SpecArg->getTemplateArgs().size(),
494-
Info, Deduced);
490+
return DeduceTemplateArguments(
491+
S, TemplateParams, Param->getArgs(), Param->getNumArgs(),
492+
SpecArg->getTemplateArgs().data(), SpecArg->getTemplateArgs().size(),
493+
Info, Deduced, /*NumberOfArgumentsMustMatch=*/true);
495494
}
496495

497496
/// \brief Determines whether the given type is an opaque type that
@@ -1461,6 +1460,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
14611460
SmallVector<const RecordType *, 8> ToVisit;
14621461
ToVisit.push_back(RecordT);
14631462
bool Successful = false;
1463+
SmallVector<DeducedTemplateArgument, 8> SuccessfulDeduced;
14641464
while (!ToVisit.empty()) {
14651465
// Retrieve the next class in the inheritance hierarchy.
14661466
const RecordType *NextT = ToVisit.pop_back_val();
@@ -1481,14 +1481,20 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
14811481
// note that we had some success. Otherwise, ignore any deductions
14821482
// from this base class.
14831483
if (BaseResult == Sema::TDK_Success) {
1484+
// If we've already seen some success, then deduction fails due to
1485+
// an ambiguity (temp.deduct.call p5).
1486+
if (Successful)
1487+
return Sema::TDK_MiscellaneousDeductionFailure;
1488+
14841489
Successful = true;
1485-
DeducedOrig.clear();
1486-
DeducedOrig.append(Deduced.begin(), Deduced.end());
1490+
std::swap(SuccessfulDeduced, Deduced);
1491+
14871492
Info.Param = BaseInfo.Param;
14881493
Info.FirstArg = BaseInfo.FirstArg;
14891494
Info.SecondArg = BaseInfo.SecondArg;
1490-
} else
1491-
Deduced = DeducedOrig;
1495+
}
1496+
1497+
Deduced = DeducedOrig;
14921498
}
14931499

14941500
// Visit base classes
@@ -1500,8 +1506,10 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
15001506
}
15011507
}
15021508

1503-
if (Successful)
1509+
if (Successful) {
1510+
std::swap(SuccessfulDeduced, Deduced);
15041511
return Sema::TDK_Success;
1512+
}
15051513

15061514
return Result;
15071515
}
@@ -1825,12 +1833,12 @@ static bool hasPackExpansionBeforeEnd(const TemplateArgument *Args,
18251833
}
18261834

18271835
static Sema::TemplateDeductionResult
1828-
DeduceTemplateArguments(Sema &S,
1829-
TemplateParameterList *TemplateParams,
1836+
DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
18301837
const TemplateArgument *Params, unsigned NumParams,
18311838
const TemplateArgument *Args, unsigned NumArgs,
18321839
TemplateDeductionInfo &Info,
1833-
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
1840+
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
1841+
bool NumberOfArgumentsMustMatch) {
18341842
// C++0x [temp.deduct.type]p9:
18351843
// If the template argument list of P contains a pack expansion that is not
18361844
// the last template argument, the entire template argument list is a
@@ -1850,7 +1858,8 @@ DeduceTemplateArguments(Sema &S,
18501858

18511859
// Check whether we have enough arguments.
18521860
if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
1853-
return Sema::TDK_Success;
1861+
return NumberOfArgumentsMustMatch ? Sema::TDK_TooFewArguments
1862+
: Sema::TDK_Success;
18541863

18551864
if (Args[ArgIdx].isPackExpansion()) {
18561865
// FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here,
@@ -1921,7 +1930,7 @@ DeduceTemplateArguments(Sema &S,
19211930
return DeduceTemplateArguments(S, TemplateParams,
19221931
ParamList.data(), ParamList.size(),
19231932
ArgList.data(), ArgList.size(),
1924-
Info, Deduced);
1933+
Info, Deduced, false);
19251934
}
19261935

19271936
/// \brief Determine whether two template arguments are the same.

‎clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,16 @@ int fn() {
160160
}
161161

162162
}
163+
164+
namespace PR28195 {
165+
166+
template<int N> struct B {};
167+
struct D : B<0>, B<1> {};
168+
169+
template<int N> int callee(B<N>); // expected-note{{failed template argument deduction}}
170+
171+
int caller() {
172+
callee(D()); // expected-error{{no matching function}}
173+
}
174+
175+
}

0 commit comments

Comments
 (0)