void ReduceClassTemplateParameter::removeOneParameterFromPartialDecl( const ClassTemplatePartialSpecializationDecl *PartialD, const TemplateArgument &Arg) { if (!Arg.isInstantiationDependent()) return; TemplateArgument::ArgKind K = Arg.getKind(); switch (K) { case TemplateArgument::Expression: removeOneParameterByArgExpression(PartialD, Arg); return; case TemplateArgument::Template: removeOneParameterByArgTemplate(PartialD, Arg); return; case TemplateArgument::Type: removeOneParameterByArgType(PartialD, Arg); return; default: TransAssert(0 && "Uncatched ArgKind!"); } TransAssert(0 && "Unreachable code!"); }
void ReduceClassTemplateParameter::removeOneParameterByArgType( const ClassTemplatePartialSpecializationDecl *PartialD, const TemplateArgument &Arg) { TransAssert((Arg.getKind() == TemplateArgument::Type) && "Arg is not TemplateArgument::Type!"); llvm::DenseMap<const Type *, unsigned> TypeToVisitsCount; llvm::DenseMap<const Type *, const NamedDecl *> TypeToNamedDecl; llvm::DenseMap<const Type *, unsigned> TypeToIndex; // retrieve all TemplateTypeParmType const TemplateParameterList *TPList = PartialD->getTemplateParameters(); unsigned Idx = 0; for (TemplateParameterList::const_iterator I = TPList->begin(), E = TPList->end(); I != E; ++I) { const NamedDecl *ND = (*I); const TemplateTypeParmDecl *TypeD = dyn_cast<TemplateTypeParmDecl>(ND); if (!TypeD) { Idx++; continue; } const Type *ParmTy = TypeD->getTypeForDecl(); TypeToVisitsCount[ParmTy] = 0; TypeToNamedDecl[ParmTy] = ND; TypeToIndex[ParmTy] = Idx; } QualType QTy = Arg.getAsType(); ArgumentDependencyVisitor V(TypeToVisitsCount); // collect TemplateTypeParmType being used by Arg V.TraverseType(QTy); llvm::DenseMap<const Type *, unsigned> DependentTypeToVisitsCount; for (llvm::DenseMap<const Type *, unsigned>::iterator I = TypeToVisitsCount.begin(), E = TypeToVisitsCount.end(); I != E; ++I) { if ((*I).second > 0) DependentTypeToVisitsCount[(*I).first] = 1; } // check if the used TemplateTypeParmType[s] have dependencies // on other Args. If yes, we cannot remove it from the parameter list. // For example: // template <typename T> // struct S <T*, T&> {}; // removing either of the arguments needs to keep the template // parameter ArgumentDependencyVisitor AccumV(DependentTypeToVisitsCount); const ASTTemplateArgumentListInfo *ArgList = PartialD->getTemplateArgsAsWritten(); const TemplateArgumentLoc *ArgLocs = ArgList->getTemplateArgs(); unsigned NumArgs = ArgList->NumTemplateArgs; TransAssert((TheParameterIndex < NumArgs) && "Bad NumArgs from partial template decl!"); for (unsigned I = 0; I < NumArgs; ++I) { if (I == TheParameterIndex) continue; const TemplateArgumentLoc ArgLoc = ArgLocs[I]; TemplateArgument OtherArg = ArgLoc.getArgument(); if (OtherArg.isInstantiationDependent() && (OtherArg.getKind() == TemplateArgument::Type)) { QualType QTy = OtherArg.getAsType(); AccumV.TraverseType(QTy); } } for (llvm::DenseMap<const Type *, unsigned>::iterator I = DependentTypeToVisitsCount.begin(), E = DependentTypeToVisitsCount.end(); I != E; ++I) { if ((*I).second != 1) continue; const NamedDecl *Param = TypeToNamedDecl[(*I).first]; TransAssert(Param && "NULL Parameter!"); SourceRange Range = Param->getSourceRange(); removeParameterByRange(Range, TPList, TypeToIndex[(*I).first]); } }