Refactor traversal of bases in deduction of template parameters from base
classes of an argument to use CXXRecordDecl::forallBases. Fix forallBases to only visit each base class once. llvm-svn: 267453
This commit is contained in:
parent
99c14524ec
commit
2eba90e0db
|
@ -137,6 +137,7 @@ CXXRecordDecl::isCurrentInstantiation(const DeclContext *CurContext) const {
|
||||||
bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches,
|
bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches,
|
||||||
bool AllowShortCircuit) const {
|
bool AllowShortCircuit) const {
|
||||||
SmallVector<const CXXRecordDecl*, 8> Queue;
|
SmallVector<const CXXRecordDecl*, 8> Queue;
|
||||||
|
llvm::SmallPtrSet<const CXXRecordDecl*, 8> Enqueued;
|
||||||
|
|
||||||
const CXXRecordDecl *Record = this;
|
const CXXRecordDecl *Record = this;
|
||||||
bool AllMatches = true;
|
bool AllMatches = true;
|
||||||
|
@ -158,12 +159,14 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches,
|
||||||
AllMatches = false;
|
AllMatches = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Queue.push_back(Base);
|
if (Enqueued.insert(Base).second) {
|
||||||
if (!BaseMatches(Base)) {
|
Queue.push_back(Base);
|
||||||
if (AllowShortCircuit) return false;
|
if (!BaseMatches(Base)) {
|
||||||
AllMatches = false;
|
if (AllowShortCircuit) return false;
|
||||||
continue;
|
AllMatches = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1454,54 +1454,35 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
|
||||||
// otherwise fail. If they yield more than one possible deduced A, the
|
// otherwise fail. If they yield more than one possible deduced A, the
|
||||||
// type deduction fails.
|
// type deduction fails.
|
||||||
|
|
||||||
// Reset the incorrectly deduced argument from above.
|
|
||||||
Deduced = DeducedOrig;
|
|
||||||
|
|
||||||
// Use data recursion to crawl through the list of base classes.
|
|
||||||
// Visited contains the set of nodes we have already visited, while
|
|
||||||
// ToVisit is our stack of records that we still need to visit.
|
|
||||||
llvm::SmallPtrSet<const RecordType *, 8> Visited;
|
|
||||||
SmallVector<const RecordType *, 8> ToVisit;
|
|
||||||
ToVisit.push_back(RecordT);
|
|
||||||
bool Successful = false;
|
bool Successful = false;
|
||||||
while (!ToVisit.empty()) {
|
RecordT->getAsCXXRecordDecl()->forallBases([&](
|
||||||
// Retrieve the next class in the inheritance hierarchy.
|
const CXXRecordDecl *Base) {
|
||||||
const RecordType *NextT = ToVisit.pop_back_val();
|
// Start with a fresh copy of the old deduced arguments.
|
||||||
|
SmallVector<DeducedTemplateArgument, 8> DeducedBase(DeducedOrig.begin(),
|
||||||
|
DeducedOrig.end());
|
||||||
|
|
||||||
// If we have already seen this type, skip it.
|
TemplateDeductionInfo BaseInfo(Info.getLocation());
|
||||||
if (!Visited.insert(NextT).second)
|
Sema::TemplateDeductionResult BaseResult =
|
||||||
continue;
|
DeduceTemplateArguments(S, TemplateParams, SpecParam,
|
||||||
|
S.Context.getRecordType(Base),
|
||||||
|
BaseInfo, DeducedBase);
|
||||||
|
|
||||||
// If this is a base class, try to perform template argument
|
// If template argument deduction for this base was successful,
|
||||||
// deduction from it.
|
// note that we had some success. Otherwise, ignore any deductions
|
||||||
if (NextT != RecordT) {
|
// from this base class.
|
||||||
TemplateDeductionInfo BaseInfo(Info.getLocation());
|
if (BaseResult == Sema::TDK_Success) {
|
||||||
Sema::TemplateDeductionResult BaseResult =
|
// FIXME: If we've already been successful, deduction should fail
|
||||||
DeduceTemplateArguments(S, TemplateParams, SpecParam,
|
// due to ambiguity.
|
||||||
QualType(NextT, 0), BaseInfo, Deduced);
|
Successful = true;
|
||||||
|
Deduced.swap(DeducedBase);
|
||||||
// If template argument deduction for this base was successful,
|
Info.Param = BaseInfo.Param;
|
||||||
// note that we had some success. Otherwise, ignore any deductions
|
Info.FirstArg = BaseInfo.FirstArg;
|
||||||
// from this base class.
|
Info.SecondArg = BaseInfo.SecondArg;
|
||||||
if (BaseResult == Sema::TDK_Success) {
|
|
||||||
Successful = true;
|
|
||||||
DeducedOrig.clear();
|
|
||||||
DeducedOrig.append(Deduced.begin(), Deduced.end());
|
|
||||||
Info.Param = BaseInfo.Param;
|
|
||||||
Info.FirstArg = BaseInfo.FirstArg;
|
|
||||||
Info.SecondArg = BaseInfo.SecondArg;
|
|
||||||
} else
|
|
||||||
Deduced = DeducedOrig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visit base classes
|
// Keep going.
|
||||||
CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
|
return true;
|
||||||
for (const auto &Base : Next->bases()) {
|
});
|
||||||
assert(Base.getType()->isRecordType() &&
|
|
||||||
"Base class that isn't a record?");
|
|
||||||
ToVisit.push_back(Base.getType()->getAs<RecordType>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Successful)
|
if (Successful)
|
||||||
return Sema::TDK_Success;
|
return Sema::TDK_Success;
|
||||||
|
|
Loading…
Reference in New Issue