bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { if (getKind() != Other.getKind()) return false; switch (getKind()) { case Null: case Type: case Declaration: case Template: case Expression: return TypeOrValue == Other.TypeOrValue; case Integral: return getIntegralType() == Other.getIntegralType() && *getAsIntegral() == *Other.getAsIntegral(); case Pack: if (Args.NumArgs != Other.Args.NumArgs) return false; for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) return false; return true; } // Suppress warnings. return false; }
void ReduceClassTemplateParameter::removeOneParameterByArgExpression( const ClassTemplatePartialSpecializationDecl *PartialD, const TemplateArgument &Arg) { TransAssert((Arg.getKind() == TemplateArgument::Expression) && "Arg is not TemplateArgument::Expression!"); const Expr *E = Arg.getAsExpr(); TransAssert(E && "Bad Expression!"); const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()); TransAssert(DRE && "Bad DeclRefExpr!"); const NonTypeTemplateParmDecl *ParmD = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()); TransAssert(ParmD && "Invalid NonTypeTemplateParmDecl!"); const TemplateParameterList *TPList = PartialD->getTemplateParameters(); unsigned Idx = 0; for (TemplateParameterList::const_iterator I = TPList->begin(), E = TPList->end(); I != E; ++I) { if ((*I) == ParmD) break; Idx++; } unsigned NumParams = TPList->size(); TransAssert((Idx < NumParams) && "Cannot find valid TemplateParameter!"); (void)NumParams; SourceRange Range = ParmD->getSourceRange(); removeParameterByRange(Range, TPList, Idx); }
void ODRHash::AddTemplateArgument(TemplateArgument TA) { const auto Kind = TA.getKind(); ID.AddInteger(Kind); switch (Kind) { case TemplateArgument::Null: llvm_unreachable("Require valid TemplateArgument"); case TemplateArgument::Type: AddQualType(TA.getAsType()); break; case TemplateArgument::Declaration: AddDecl(TA.getAsDecl()); break; case TemplateArgument::NullPtr: AddQualType(TA.getNullPtrType()); break; case TemplateArgument::Integral: TA.getAsIntegral().Profile(ID); AddQualType(TA.getIntegralType()); break; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: AddTemplateName(TA.getAsTemplateOrTemplatePattern()); break; case TemplateArgument::Expression: AddStmt(TA.getAsExpr()); break; case TemplateArgument::Pack: ID.AddInteger(TA.pack_size()); for (auto SubTA : TA.pack_elements()) AddTemplateArgument(SubTA); break; } }
/// \brief Print a template integral argument value. /// /// \param TemplArg the TemplateArgument instance to print. /// /// \param Out the raw_ostream instance to use for printing. /// /// \param Policy the printing policy for EnumConstantDecl printing. static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out, const PrintingPolicy& Policy) { const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); const llvm::APSInt &Val = TemplArg.getAsIntegral(); if (const EnumType *ET = T->getAs<EnumType>()) { for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) { // In Sema::CheckTemplateArugment, enum template arguments value are // extended to the size of the integer underlying the enum type. This // may create a size difference between the enum value and template // argument value, requiring isSameValue here instead of operator==. if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) { ECD->printQualifiedName(Out, Policy); return; } } } if (T->isBooleanType() && !Policy.MSVCFormatting) { Out << (Val.getBoolValue() ? "true" : "false"); } else if (T->isCharType()) { const char Ch = Val.getZExtValue(); Out << ((Ch == '\'') ? "'\\" : "'"); Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true); Out << "'"; } else { Out << Val; } }
void ReduceClassTemplateParameter::removeOneParameterByArgTemplate( const ClassTemplatePartialSpecializationDecl *PartialD, const TemplateArgument &Arg) { TransAssert((Arg.getKind() == TemplateArgument::Template) && "Arg is not TemplateArgument::Template!"); TemplateName TmplName = Arg.getAsTemplate(); TransAssert((TmplName.getKind() == TemplateName::Template) && "Invalid TemplateName Kind!"); const TemplateDecl *TmplD = TmplName.getAsTemplateDecl(); const TemplateParameterList *TPList = PartialD->getTemplateParameters(); unsigned Idx = 0; for (TemplateParameterList::const_iterator I = TPList->begin(), E = TPList->end(); I != E; ++I) { if ((*I) == TmplD) break; Idx++; } unsigned NumParams = TPList->size(); TransAssert((Idx < NumParams) && "Cannot find valid TemplateParameter!"); (void)NumParams; SourceRange Range = TmplD->getSourceRange(); removeParameterByRange(Range, TPList, Idx); return; }
bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { if (getKind() != Other.getKind()) return false; switch (getKind()) { case Null: case Type: case Expression: case Template: case TemplateExpansion: case NullPtr: return TypeOrValue.V == Other.TypeOrValue.V; case Declaration: return getAsDecl() == Other.getAsDecl() && isDeclForReferenceParam() && Other.isDeclForReferenceParam(); case Integral: return getIntegralType() == Other.getIntegralType() && getAsIntegral() == Other.getAsIntegral(); case Pack: if (Args.NumArgs != Other.Args.NumArgs) return false; for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) return false; return true; } llvm_unreachable("Invalid TemplateArgument Kind!"); }
bool TemplateNonTypeArgToInt::isValidTemplateArgument( const TemplateArgument &Arg) { TemplateArgument::ArgKind K = Arg.getKind(); switch (K) { case TemplateArgument::Declaration: { return true; } case TemplateArgument::Expression: { const Expr *E = Arg.getAsExpr()->IgnoreParenCasts(); if (dyn_cast<IntegerLiteral>(E) || dyn_cast<CXXBoolLiteralExpr>(E)) return false; if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { UnaryOperator::Opcode Op = UO->getOpcode(); if((Op == UO_Minus) || (Op == UO_Plus)) return false; } return true; } default: TransAssert(0 && "Unreachable code!"); return false; } TransAssert(0 && "Unreachable code!"); return false; }
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 StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { // Mostly repetitive with TemplateArgument::Profile! ID.AddInteger(Arg.getKind()); switch (Arg.getKind()) { case TemplateArgument::Null: break; case TemplateArgument::Type: VisitType(Arg.getAsType()); break; case TemplateArgument::Template: VisitTemplateName(Arg.getAsTemplate()); break; case TemplateArgument::Declaration: VisitDecl(Arg.getAsDecl()); break; case TemplateArgument::Integral: Arg.getAsIntegral()->Profile(ID); VisitType(Arg.getIntegralType()); break; case TemplateArgument::Expression: Visit(Arg.getAsExpr()); break; case TemplateArgument::Pack: const TemplateArgument *Pack = Arg.pack_begin(); for (unsigned i = 0, e = Arg.pack_size(); i != e; ++i) VisitTemplateArgument(Pack[i]); break; } }
SubstNonTypeTemplateParmPackExpr:: SubstNonTypeTemplateParmPackExpr(QualType T, NonTypeTemplateParmDecl *Param, SourceLocation NameLoc, const TemplateArgument &ArgPack) : Expr(SubstNonTypeTemplateParmPackExprClass, T, VK_RValue, OK_Ordinary, true, true, true, true), Param(Param), Arguments(ArgPack.pack_begin()), NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { }
static void describeTemplateParameter(raw_ostream &Out, const TemplateArgument &TArg, const LangOptions &LO) { if (TArg.getKind() == TemplateArgument::ArgKind::Pack) { describeTemplateParameters(Out, TArg.getPackAsArray(), LO); } else { TArg.print(PrintingPolicy(LO), Out); } }
Type * TypeCheck::visit(TemplateArgumentList *ast) { FUNCLOG; List<TemplateArgument*>::iterator it = ast->args.begin(); while (it != ast->args.end()) { TemplateArgument *arg = *it; arg->accept(this); ++it; } return NULL; }
bool InstantiateTemplateParam::getTemplateArgumentString(const TemplateArgument &Arg, std::string &ArgStr, std::string &ForwardStr) { ArgStr = ""; ForwardStr = ""; if (Arg.getKind() != TemplateArgument::Type) return false; QualType QT = Arg.getAsType(); return getTypeString(QT, ArgStr, ForwardStr); }
CXType clang_Cursor_getTemplateArgumentType(CXCursor C, unsigned I) { TemplateArgument TA; if (clang_Cursor_getTemplateArgument(C, I, &TA) != CXGetTemplateArgumentStatus_Success) { return cxtype::MakeCXType(QualType(), getCursorTU(C)); } if (TA.getKind() != TemplateArgument::Type) { return cxtype::MakeCXType(QualType(), getCursorTU(C)); } return cxtype::MakeCXType(TA.getAsType(), getCursorTU(C)); }
Optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) { assert(Arg.containsUnexpandedParameterPack()); // If this is a substituted pack, grab that pack. If not, we don't know // the size yet. // FIXME: We could find a size in more cases by looking for a substituted // pack anywhere within this argument, but that's not necessary in the common // case for 'sizeof...(A)' handling. TemplateArgument Pack; switch (Arg.getKind()) { case TemplateArgument::Type: if (auto *Subst = Arg.getAsType()->getAs<SubstTemplateTypeParmPackType>()) Pack = Subst->getArgumentPack(); else return None; break; case TemplateArgument::Expression: if (auto *Subst = dyn_cast<SubstNonTypeTemplateParmPackExpr>(Arg.getAsExpr())) Pack = Subst->getArgumentPack(); else if (auto *Subst = dyn_cast<FunctionParmPackExpr>(Arg.getAsExpr())) { for (ParmVarDecl *PD : *Subst) if (PD->isParameterPack()) return None; return Subst->getNumExpansions(); } else return None; break; case TemplateArgument::Template: if (SubstTemplateTemplateParmPackStorage *Subst = Arg.getAsTemplate().getAsSubstTemplateTemplateParmPack()) Pack = Subst->getArgumentPack(); else return None; break; case TemplateArgument::Declaration: case TemplateArgument::NullPtr: case TemplateArgument::TemplateExpansion: case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Null: return None; } // Check that no argument in the pack is itself a pack expansion. for (TemplateArgument Elem : Pack.pack_elements()) { // There's no point recursing in this case; we would have already // expanded this pack expansion into the enclosing pack if we could. if (Elem.isPackExpansion()) return None; } return Pack.pack_size(); }
long long clang_Cursor_getTemplateArgumentValue(CXCursor C, unsigned I) { TemplateArgument TA; if (clang_Cursor_getTemplateArgument(C, I, &TA) != CXGetTemplateArgumentStatus_Success) { assert(0 && "Unable to retrieve TemplateArgument"); return 0; } if (TA.getKind() != TemplateArgument::Integral) { assert(0 && "Passed template argument is not Integral"); return 0; } return TA.getAsIntegral().getSExtValue(); }
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, TemplateTemplateParmDecl *Parameter, const TemplateArgument &ArgPack) { ID.AddPointer(Parameter); ArgPack.Profile(ID, Context); }
/// \brief Print a template integral argument value. /// /// \param TemplArg the TemplateArgument instance to print. /// /// \param Out the raw_ostream instance to use for printing. static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out) { const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); const llvm::APSInt &Val = TemplArg.getAsIntegral(); if (T->isBooleanType()) { Out << (Val.getBoolValue() ? "true" : "false"); } else if (T->isCharType()) { const char Ch = Val.getZExtValue(); Out << ((Ch == '\'') ? "'\\" : "'"); Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true); Out << "'"; } else { Out << Val; } }
void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) { switch (Arg.getKind()) { default: break; case TemplateArgument::Type: assert(Arg.getAsType().isCanonical() && "Type must be canonical!"); break; } assert(NumFlatArgs < MaxFlatArgs && "Argument list builder is full!"); assert(!StructuredArgs && "Can't append arguments when an argument pack has been added!"); if (!FlatArgs) FlatArgs = new TemplateArgument[MaxFlatArgs]; FlatArgs[NumFlatArgs++] = Arg; }
// Get |count| number of template arguments. Returns false if there // are fewer than |count| arguments or any of the arguments are not // of a valid Type structure. If |count| is non-positive, all // arguments are collected. bool RecordInfo::GetTemplateArgs(size_t count, TemplateArgs* output_args) { ClassTemplateSpecializationDecl* tmpl = dyn_cast<ClassTemplateSpecializationDecl>(record_); if (!tmpl) return false; const TemplateArgumentList& args = tmpl->getTemplateArgs(); if (args.size() < count) return false; if (count <= 0) count = args.size(); for (unsigned i = 0; i < count; ++i) { TemplateArgument arg = args[i]; if (arg.getKind() == TemplateArgument::Type && !arg.getAsType().isNull()) { output_args->push_back(arg.getAsType().getTypePtr()); } else { return false; } } return true; }
void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) { IndentScope Indent(*this); OS << "TemplateArgument"; if (R.isValid()) dumpSourceRange(R); switch (A.getKind()) { case TemplateArgument::Null: OS << " null"; break; case TemplateArgument::Type: OS << " type"; dumpType(A.getAsType()); break; case TemplateArgument::Declaration: OS << " decl"; dumpDeclRef(A.getAsDecl()); break; case TemplateArgument::NullPtr: OS << " nullptr"; break; case TemplateArgument::Integral: OS << " integral " << A.getAsIntegral(); break; case TemplateArgument::Template: OS << " template "; A.getAsTemplate().dump(OS); break; case TemplateArgument::TemplateExpansion: OS << " template expansion"; A.getAsTemplateOrTemplatePattern().dump(OS); break; case TemplateArgument::Expression: OS << " expr"; dumpStmt(A.getAsExpr()); break; case TemplateArgument::Pack: OS << " pack"; for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end(); I != E; ++I) dumpTemplateArgument(*I); break; } }
void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { // Mostly repetitive with TemplateArgument::Profile! ID.AddInteger(Arg.getKind()); switch (Arg.getKind()) { case TemplateArgument::Null: break; case TemplateArgument::Type: VisitType(Arg.getAsType()); break; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); break; case TemplateArgument::Declaration: VisitDecl(Arg.getAsDecl()); break; case TemplateArgument::NullPtr: VisitType(Arg.getNullPtrType()); break; case TemplateArgument::Integral: Arg.getAsIntegral().Profile(ID); VisitType(Arg.getIntegralType()); break; case TemplateArgument::Expression: Visit(Arg.getAsExpr()); break; case TemplateArgument::Pack: for (const auto &P : Arg.pack_elements()) VisitTemplateArgument(P); break; } }
enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C, unsigned I) { TemplateArgument TA; if (clang_Cursor_getTemplateArgument(C, I, &TA)) { return CXTemplateArgumentKind_Invalid; } switch (TA.getKind()) { case TemplateArgument::Null: return CXTemplateArgumentKind_Null; case TemplateArgument::Type: return CXTemplateArgumentKind_Type; case TemplateArgument::Declaration: return CXTemplateArgumentKind_Declaration; case TemplateArgument::NullPtr: return CXTemplateArgumentKind_NullPtr; case TemplateArgument::Integral: return CXTemplateArgumentKind_Integral; case TemplateArgument::Template: return CXTemplateArgumentKind_Template; case TemplateArgument::TemplateExpansion: return CXTemplateArgumentKind_TemplateExpansion; case TemplateArgument::Expression: return CXTemplateArgumentKind_Expression; case TemplateArgument::Pack: return CXTemplateArgumentKind_Pack; } return CXTemplateArgumentKind_Invalid; }
void InstantiateTemplateParam::getForwardDeclStr( const Type *Ty, std::string &ForwardStr, RecordDeclSet &TempAvailableRecordDecls) { if (const RecordType *RT = Ty->getAsUnionType()) { const RecordDecl *RD = RT->getDecl(); addOneForwardDeclStr(RD, ForwardStr, TempAvailableRecordDecls); return; } const CXXRecordDecl *CXXRD = Ty->getAsCXXRecordDecl(); if (!CXXRD) return; const ClassTemplateSpecializationDecl *SpecD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD); if (!SpecD) { addOneForwardDeclStr(CXXRD, ForwardStr, TempAvailableRecordDecls); return; } addForwardTemplateDeclStr(SpecD->getSpecializedTemplate(), ForwardStr, TempAvailableRecordDecls); const TemplateArgumentList &ArgList = SpecD->getTemplateArgs(); unsigned NumArgs = ArgList.size(); for (unsigned I = 0; I < NumArgs; ++I) { const TemplateArgument Arg = ArgList[I]; if (Arg.getKind() != TemplateArgument::Type) continue; getForwardDeclStr(Arg.getAsType().getTypePtr(), ForwardStr, TempAvailableRecordDecls); } }
void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { switch (Arg.getKind()) { case TemplateArgument::Null: break; case TemplateArgument::Declaration: Visit(Arg.getAsDecl()); break; case TemplateArgument::NullPtr: break; case TemplateArgument::TemplateExpansion: Out << 'P'; // pack expansion of... // Fall through case TemplateArgument::Template: VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); break; case TemplateArgument::Expression: // FIXME: Visit expressions. break; case TemplateArgument::Pack: Out << 'p' << Arg.pack_size(); for (TemplateArgument::pack_iterator P = Arg.pack_begin(), PEnd = Arg.pack_end(); P != PEnd; ++P) VisitTemplateArgument(*P); break; case TemplateArgument::Type: VisitType(Arg.getAsType()); break; case TemplateArgument::Integral: Out << 'V'; VisitType(Arg.getIntegralType()); Out << Arg.getAsIntegral(); break; } }
static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx, TemplateArgument &Arg) { bool Changed = false; // Note: we do not handle TemplateArgument::Expression, to replace it // we need the information for the template instance decl. if (Arg.getKind() == TemplateArgument::Template) { TemplateName TName = Arg.getAsTemplate(); Changed = getFullyQualifiedTemplateName(Ctx, TName); if (Changed) { Arg = TemplateArgument(TName); } } else if (Arg.getKind() == TemplateArgument::Type) { QualType SubTy = Arg.getAsType(); // Check if the type needs more desugaring and recurse. QualType QTFQ = getFullyQualifiedType(SubTy, Ctx); if (QTFQ != SubTy) { Arg = TemplateArgument(QTFQ); Changed = true; } } return Changed; }
string getTemplateArgumentName(const TemplateArgument & argument) { string qualifiedName; switch(argument.getKind()) { case TemplateArgument::Null: qualifiedName = "NULL"; break; case TemplateArgument::Type: qualifiedName = CppType(argument.getAsType()).getQualifiedName(); break; case TemplateArgument::Declaration: qualifiedName = dyn_cast<NamedDecl>(argument.getAsDecl())->getQualifiedNameAsString(); break; case TemplateArgument::Integral: case TemplateArgument::Expression: qualifiedName = exprToText(argument.getAsExpr()); break; case TemplateArgument::Template: qualifiedName = argument.getAsTemplate().getAsTemplateDecl()->getQualifiedNameAsString(); break; case TemplateArgument::TemplateExpansion: break; case TemplateArgument::Pack: break; } return qualifiedName; }
void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { switch (Arg.getKind()) { case TemplateArgument::Null: break; case TemplateArgument::Declaration: Visit(Arg.getAsDecl()); break; case TemplateArgument::NullPtr: break; case TemplateArgument::TemplateExpansion: Out << 'P'; // pack expansion of... LLVM_FALLTHROUGH; case TemplateArgument::Template: VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); break; case TemplateArgument::Expression: // FIXME: Visit expressions. break; case TemplateArgument::Pack: Out << 'p' << Arg.pack_size(); for (const auto &P : Arg.pack_elements()) VisitTemplateArgument(P); break; case TemplateArgument::Type: VisitType(Arg.getAsType()); break; case TemplateArgument::Integral: Out << 'V'; VisitType(Arg.getIntegralType()); Out << Arg.getAsIntegral(); break; } }
static void PrintTemplateArgument(std::string &Buffer, const TemplateArgument &Arg, const PrintingPolicy &Policy) { switch (Arg.getKind()) { case TemplateArgument::Null: assert(false && "Null template argument"); break; case TemplateArgument::Type: Arg.getAsType().getAsStringInternal(Buffer, Policy); break; case TemplateArgument::Declaration: Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString(); break; case TemplateArgument::Template: { llvm::raw_string_ostream s(Buffer); Arg.getAsTemplate().print(s, Policy); break; } case TemplateArgument::Integral: Buffer = Arg.getAsIntegral()->toString(10, true); break; case TemplateArgument::Expression: { llvm::raw_string_ostream s(Buffer); Arg.getAsExpr()->printPretty(s, 0, Policy); break; } case TemplateArgument::Pack: assert(0 && "FIXME: Implement!"); break; } }
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]); } }