void TemplateArgToInt::handleOneType(const Type *Ty)
{
  if (Ty->isPointerType() || Ty->isReferenceType())
    Ty = getBasePointerElemType(Ty);
  const SubstTemplateTypeParmType *SubstType = getSubstTemplateTypeParmType(Ty);
  if (!SubstType)
    return;

  const TemplateTypeParmType *ParmType = SubstType->getReplacedParameter();
  TemplateTypeParmDecl *ParmDecl = ParmType->getDecl();
  TransAssert(ParmDecl && "Invalid ParmDecl!");
  const TemplateDecl *TmplD = ParamToTemplateDecl[ParmDecl];
  if (TmplD == NULL) {
    const DeclContext *Ctx = ParmDecl->getDeclContext();
    TransAssert(Ctx && "NULL Ctx!");
    const ClassTemplateSpecializationDecl *Spec = 
      dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
    TransAssert(Spec && "Not a ClassTemplateSpecializationDecl!");
    TmplD = Spec->getSpecializedTemplate();
  }
  TransAssert(TmplD && "NULL TemplateDecl!");
  TemplateParameterIdxSet *InvalidIdx = 
    DeclToParamIdx[dyn_cast<TemplateDecl>(TmplD->getCanonicalDecl())];
  TransAssert(InvalidIdx && "NULL InvalidIdx!");
  InvalidIdx->insert(ParmType->getIndex());
}
void TemplateArgToInt::handleTemplateArgumentLocs(
       const TemplateDecl *D, const TemplateArgumentLoc *TAL, unsigned NumArgs)
{
  TransAssert(D && "NULL TemplateDecl!");
  if (!TAL)
    return;
  TemplateParameterIdxSet *InvalidIdx = 
    DeclToParamIdx[dyn_cast<TemplateDecl>(D->getCanonicalDecl())];
  if (!InvalidIdx)
    return;
  for (unsigned I = 0; I < NumArgs; ++I) {
    if (!InvalidIdx->count(I))
      handleOneTemplateArgumentLoc(TAL[I]);
  }
}
void TemplateArgToInt::handleTemplateSpecializationTypeLoc(
       const TemplateSpecializationTypeLoc &TLoc)
{
  const Type *Ty = TLoc.getTypePtr();
  const TemplateSpecializationType *TST = 
    Ty->getAs<TemplateSpecializationType>();
  TemplateName TplName = TST->getTemplateName();
  const TemplateDecl *TplD = TplName.getAsTemplateDecl();

  TemplateParameterIdxSet *InvalidIdx = 
    DeclToParamIdx[dyn_cast<TemplateDecl>(TplD->getCanonicalDecl())];
  if (!InvalidIdx)
    return;
  for (unsigned I = 0; I < TLoc.getNumArgs(); ++I) {
    if (!InvalidIdx->count(I))
      handleOneTemplateArgumentLoc(TLoc.getArgLoc(I));
  }
}
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++;
  }
}
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;
}