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;
    }
  }
}
Example #2
0
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++;
  }
}
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;
}