QualType ClassTemplateDecl::getInjectedClassNameSpecialization() { Common *CommonPtr = getCommonPtr(); if (!CommonPtr->InjectedClassNameType.isNull()) return CommonPtr->InjectedClassNameType; // C++0x [temp.dep.type]p2: // The template argument list of a primary template is a template argument // list in which the nth template argument has the value of the nth template // parameter of the class template. If the nth template parameter is a // template parameter pack (14.5.3), the nth template argument is a pack // expansion (14.5.3) whose pattern is the name of the template parameter // pack. ASTContext &Context = getASTContext(); TemplateParameterList *Params = getTemplateParameters(); llvm::SmallVector<TemplateArgument, 16> TemplateArgs; TemplateArgs.reserve(Params->size()); for (TemplateParameterList::iterator Param = Params->begin(), ParamEnd = Params->end(); Param != ParamEnd; ++Param) { TemplateArgument Arg; if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { QualType ArgType = Context.getTypeDeclType(TTP); if (TTP->isParameterPack()) ArgType = Context.getPackExpansionType(ArgType, llvm::Optional<unsigned>()); Arg = TemplateArgument(ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType().getNonLValueExprType(Context), Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); if (NTTP->isParameterPack()) E = new (Context) PackExpansionExpr(Context.DependentTy, E, NTTP->getLocation(), llvm::Optional<unsigned>()); Arg = TemplateArgument(E); } else { TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); if (TTP->isParameterPack()) Arg = TemplateArgument(TemplateName(TTP), llvm::Optional<unsigned>()); else Arg = TemplateArgument(TemplateName(TTP)); } if ((*Param)->isTemplateParameterPack()) Arg = TemplateArgument::CreatePackCopy(Context, &Arg, 1); TemplateArgs.push_back(Arg); } CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(TemplateName(this), &TemplateArgs[0], TemplateArgs.size()); return CommonPtr->InjectedClassNameType; }
QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) { if (!CommonPtr->InjectedClassNameType.isNull()) return CommonPtr->InjectedClassNameType; // FIXME: n2800 14.6.1p1 should say how the template arguments // corresponding to template parameter packs should be pack // expansions. We already say that in 14.6.2.1p2, so it would be // better to fix that redundancy. TemplateParameterList *Params = getTemplateParameters(); llvm::SmallVector<TemplateArgument, 16> TemplateArgs; TemplateArgs.reserve(Params->size()); for (TemplateParameterList::iterator Param = Params->begin(), ParamEnd = Params->end(); Param != ParamEnd; ++Param) { if (isa<TemplateTypeParmDecl>(*Param)) { QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param)); TemplateArgs.push_back(TemplateArgument(ParamType)); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(), NTTP->getLocation()); TemplateArgs.push_back(TemplateArgument(E)); } else { TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); TemplateArgs.push_back(TemplateArgument(TemplateName(TTP))); } } CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(TemplateName(this), &TemplateArgs[0], TemplateArgs.size()); return CommonPtr->InjectedClassNameType; }
bool ClassTemplateToClass::isValidClassTemplateDecl(ClassTemplateDecl *TmplD) { TemplateParameterList *TPList = TmplD->getTemplateParameters(); if (TPList->size() != 1) return false; CXXRecordDecl *CXXRD = TmplD->getTemplatedDecl(); CXXRecordDecl *Def = CXXRD->getDefinition(); if (!Def) return true; NamedDecl *ND = TPList->getParam(0); if (dyn_cast<NonTypeTemplateParmDecl>(ND)) return true; if (isUsedNamedDecl(ND, Def)) return false; SmallVector<ClassTemplatePartialSpecializationDecl *, 10> PartialDecls; TmplD->getPartialSpecializations(PartialDecls); for (SmallVector<ClassTemplatePartialSpecializationDecl *, 10>::iterator I = PartialDecls.begin(), E = PartialDecls.end(); I != E; ++I) { if (hasUsedNameDecl(*I)) return false; } return true; }
ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() { TemplateParameterList *Params = getTemplateParameters(); Common *CommonPtr = getCommonPtr(); if (!CommonPtr->InjectedArgs) { CommonPtr->InjectedArgs = new (getASTContext()) TemplateArgument[Params->size()]; GenerateInjectedTemplateArgs(getASTContext(), Params, CommonPtr->InjectedArgs); } return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size()); }
void InstantiateTemplateParam::removeTemplateKeyword() { if (dyn_cast<ClassTemplateDecl>(TheTemplateDecl)) return; TemplateParameterList *TPList = TheTemplateDecl->getTemplateParameters(); if (TPList->size() != 1) return; const NamedDecl *ND = TPList->getParam(0); (void)ND; TransAssert((ND == TheParameter) && "Invalid template parameter!"); TheRewriter.RemoveText(SourceRange(TPList->getTemplateLoc(), TPList->getRAngleLoc())); }
std::pair<const TemplateArgument *, unsigned> FunctionTemplateDecl::getInjectedTemplateArgs() { TemplateParameterList *Params = getTemplateParameters(); Common *CommonPtr = getCommonPtr(); if (!CommonPtr->InjectedArgs) { CommonPtr->InjectedArgs = new (getASTContext()) TemplateArgument [Params->size()]; GenerateInjectedTemplateArgs(getASTContext(), Params, CommonPtr->InjectedArgs); } return std::make_pair(CommonPtr->InjectedArgs, Params->size()); }
void InstantiateTemplateParam::handleOneTemplateSpecialization( const TemplateDecl *D, const TemplateArgumentList & ArgList) { if (isInIncludedFile(D)) return; NamedDecl *ND = D->getTemplatedDecl(); TemplateParameterSet ParamsSet; TemplateParameterVisitor ParameterVisitor(ParamsSet); ParameterVisitor.TraverseDecl(ND); if (ParamsSet.size() == 0) return; unsigned NumArgs = ArgList.size(); (void)NumArgs; unsigned Idx = 0; TemplateParameterList *TPList = D->getTemplateParameters(); for (TemplateParameterList::const_iterator I = TPList->begin(), E = TPList->end(); I != E; ++I) { const NamedDecl *ND = (*I); // make it simple, skip NonTypeTemplateParmDecl and // TemplateTemplateParmDecl for now const TemplateTypeParmDecl *TyParmDecl = dyn_cast<TemplateTypeParmDecl>(ND); if (!TyParmDecl || TyParmDecl->isParameterPack() || !ParamsSet.count(ND)) { Idx++; continue; } TransAssert((Idx < NumArgs) && "Invalid Idx!"); const TemplateArgument &Arg = ArgList.get(Idx); std::string ArgStr; std::string ForwardStr; if (!getTemplateArgumentString(Arg, ArgStr, ForwardStr)) continue; ValidInstanceNum++; if (ValidInstanceNum == TransformationCounter) { TheInstantiationString = ArgStr; TheParameter = ND; TheTemplateDecl = D; TheForwardDeclString = ForwardStr; } } }
void TemplateArgToInt::collectInvalidParamIdx( const TemplateDecl *D, TemplateParameterIdxSet &InvalidParamIdx) { TemplateParameterSet InvalidParams; NamedDecl *ND = D->getTemplatedDecl(); TemplateInvalidParameterVisitor ParameterVisitor(InvalidParams, this); ParameterVisitor.TraverseDecl(ND); TemplateParameterList *TPList = D->getTemplateParameters(); unsigned Idx = 0; for (TemplateParameterList::const_iterator I = TPList->begin(), E = TPList->end(); I != E; ++I) { const NamedDecl *ParamND = (*I); ParamToTemplateDecl[ParamND] = D; if (InvalidParams.count(ParamND)) { TransAssert(!InvalidParamIdx.count(Idx) && "Duplicate Index!"); InvalidParamIdx.insert(Idx); } Idx++; } }
QualType ClassTemplateDecl::getInjectedClassNameSpecialization() { Common *CommonPtr = getCommonPtr(); if (!CommonPtr->InjectedClassNameType.isNull()) return CommonPtr->InjectedClassNameType; // C++0x [temp.dep.type]p2: // The template argument list of a primary template is a template argument // list in which the nth template argument has the value of the nth template // parameter of the class template. If the nth template parameter is a // template parameter pack (14.5.3), the nth template argument is a pack // expansion (14.5.3) whose pattern is the name of the template parameter // pack. ASTContext &Context = getASTContext(); TemplateParameterList *Params = getTemplateParameters(); SmallVector<TemplateArgument, 16> TemplateArgs; TemplateArgs.resize(Params->size()); GenerateInjectedTemplateArgs(getASTContext(), Params, TemplateArgs.data()); CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(TemplateName(this), &TemplateArgs[0], TemplateArgs.size()); return CommonPtr->InjectedClassNameType; }
bool ClassTemplateToClass::hasUsedNameDecl( ClassTemplatePartialSpecializationDecl *PartialD) { if (!PartialD->isCompleteDefinition()) return false; SmallPtrSet<NamedDecl *, 8> Params; TemplateParameterList *PartialTPList = PartialD->getTemplateParameters(); for (unsigned PI = 0; PI < PartialTPList->size(); ++PI) { NamedDecl *ND = PartialTPList->getParam(PI); if (dyn_cast<NonTypeTemplateParmDecl>(ND)) continue; Params.insert(ND); } TemplateParameterTypeVisitor ParamVisitor(Context); // Skip visiting parameters and arguments for (CXXRecordDecl::base_class_iterator I = PartialD->bases_begin(), E = PartialD->bases_end(); I != E; ++I) { ParamVisitor.TraverseType(I->getType()); } DeclContext *Ctx = dyn_cast<DeclContext>(PartialD); for (DeclContext::decl_iterator DI = Ctx->decls_begin(), DE = Ctx->decls_end(); DI != DE; ++DI) { ParamVisitor.TraverseDecl(*DI); } for (SmallPtrSet<NamedDecl *, 8>::iterator I = Params.begin(), E = Params.end(); I != E; ++I) { if (ParamVisitor.isAUsedParameter(*I)) return true; } return false; }
void TemplateNonTypeArgToInt::handleOneTemplateDecl(const TemplateDecl *D) { if (isInIncludedFile(D)) return; TemplateParameterIdxSet *ValidParamIdx = new TemplateParameterIdxSet(); TemplateParameterList *TPList = D->getTemplateParameters(); unsigned Idx = 0; for (TemplateParameterList::const_iterator I = TPList->begin(), E = TPList->end(); I != E; ++I) { const NamedDecl *ParamND = (*I); if (isValidParameter(ParamND)) { ValidParamIdx->insert(Idx); if (const ValueDecl* ValD = dyn_cast<ValueDecl>(ParamND)) { ++ValidInstanceNum; if (ValidInstanceNum == TransformationCounter) TheValueDecl = ValD; } } Idx++; } TransAssert(!DeclToParamIdx[D] && "Duplicate TemplateDecl!"); DeclToParamIdx[dyn_cast<TemplateDecl>(D->getCanonicalDecl())] = ValidParamIdx; }
bool ReduceClassTemplateParameterASTVisitor::VisitClassTemplateDecl( ClassTemplateDecl *D) { if (ConsumerInstance->isInIncludedFile(D)) return true; ClassTemplateDecl *CanonicalD = D->getCanonicalDecl(); if (ConsumerInstance->VisitedDecls.count(CanonicalD)) return true; ConsumerInstance->VisitedDecls.insert(CanonicalD); if (!ConsumerInstance->isValidClassTemplateDecl(D)) return true; TemplateParameterSet ParamsSet; TemplateParameterVisitor ParameterVisitor(ParamsSet); CXXRecordDecl *CXXRD = D->getTemplatedDecl(); CXXRecordDecl *Def = CXXRD->getDefinition(); if (Def) ParameterVisitor.TraverseDecl(Def); // ISSUE: we should also check the parameter usage for partial template // specializations. For example: // template<typename T1, typename T2> struct S{}; // template<typename T1, typename T2> struct<T1 *, T2 *> S{...}; // T1 or T2 could be used in "..." // Also, we could have another bad transformation, for example, // template<bool, typename T> struct S{}; // template<typename T> struct<true, T> S{}; // if we remove bool and true, we will have two definitions for S TemplateParameterList *TPList; if (Def) { // make sure we use the params as in ParameterVisitor const ClassTemplateDecl *CT = Def->getDescribedClassTemplate(); TransAssert(CT && "NULL DescribedClassTemplate!"); TPList = CT->getTemplateParameters(); } else { TPList = CanonicalD->getTemplateParameters(); } unsigned Index = 0; for (TemplateParameterList::const_iterator I = TPList->begin(), E = TPList->end(); I != E; ++I) { const NamedDecl *ND = (*I); if (ParamsSet.count(ND)) { Index++; continue; } ConsumerInstance->ValidInstanceNum++; if (ConsumerInstance->ValidInstanceNum == ConsumerInstance->TransformationCounter) { ConsumerInstance->TheClassTemplateDecl = CanonicalD; ConsumerInstance->TheParameterIndex = Index; ConsumerInstance->TheTemplateName = new TemplateName(CanonicalD); ConsumerInstance->setDefaultArgFlag(ND); } Index++; } return true; }