Beispiel #1
0
int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
    if (LHS.getNameKind() != RHS.getNameKind())
        return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);

    switch (LHS.getNameKind()) {
    case DeclarationName::Identifier: {
        IdentifierInfo *LII = LHS.getAsIdentifierInfo();
        IdentifierInfo *RII = RHS.getAsIdentifierInfo();
        if (!LII) return RII ? -1 : 0;
        if (!RII) return 1;

        return LII->getName().compare(RII->getName());
    }

    case DeclarationName::ObjCZeroArgSelector:
    case DeclarationName::ObjCOneArgSelector:
    case DeclarationName::ObjCMultiArgSelector: {
        Selector LHSSelector = LHS.getObjCSelector();
        Selector RHSSelector = RHS.getObjCSelector();
        unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
        for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
            switch (LHSSelector.getNameForSlot(I).compare(
                        RHSSelector.getNameForSlot(I))) {
            case -1:
                return true;
            case 1:
                return false;
            default:
                break;
            }
        }

        return compareInt(LN, RN);
    }

    case DeclarationName::CXXConstructorName:
    case DeclarationName::CXXDestructorName:
    case DeclarationName::CXXConversionFunctionName:
        if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
            return -1;
        if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
            return 1;
        return 0;

    case DeclarationName::CXXOperatorName:
        return compareInt(LHS.getCXXOverloadedOperator(),
                          RHS.getCXXOverloadedOperator());

    case DeclarationName::CXXLiteralOperatorName:
        return LHS.getCXXLiteralIdentifier()->getName().compare(
                   RHS.getCXXLiteralIdentifier()->getName());

    case DeclarationName::CXXUsingDirective:
        return 0;
    }

    return 0;
}
Beispiel #2
0
DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
  switch (Name.getNameKind()) {
  case DeclarationName::Identifier:
    break;
  case DeclarationName::CXXConstructorName:
  case DeclarationName::CXXDestructorName:
  case DeclarationName::CXXConversionFunctionName:
    NamedType.TInfo = nullptr;
    break;
  case DeclarationName::CXXOperatorName:
    CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
    CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
    break;
  case DeclarationName::CXXLiteralOperatorName:
    CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
    break;
  case DeclarationName::ObjCZeroArgSelector:
  case DeclarationName::ObjCOneArgSelector:
  case DeclarationName::ObjCMultiArgSelector:
    // FIXME: ?
    break;
  case DeclarationName::CXXUsingDirective:
    break;
  }
}
void RemoveUnusedFunction::handleOneCXXDependentScopeMemberExpr(
       const FunctionDecl *CurrentFD,
       const CXXDependentScopeMemberExpr *E)
{
  if (E->isImplicitAccess())
    return;
  DeclarationName DName = E->getMember();
  DeclarationName::NameKind K = DName.getNameKind();
  if ((K != DeclarationName::CXXOperatorName) &&
      (K != DeclarationName::Identifier))
    return;
  const Expr *Base = E->getBase()->IgnoreParenCasts();
  const FunctionDecl *FD = NULL;
  if (dyn_cast<CXXThisExpr>(Base)) {
    TransAssert(CurrentFD && "NULL CurrentFD");
    const DeclContext *Ctx = CurrentFD->getLookupParent();
    TransAssert(Ctx && "Bad DeclContext!");
    DeclContextSet VisitedCtxs;
    FD = lookupFunctionDecl(DName, Ctx, VisitedCtxs);
    // we may not get FD in cases where we have this->m_field
    if (FD)
      addOneReferencedFunction(FD);
    return;
  }
}
Beispiel #4
0
bool operator<(DeclarationName LHS, DeclarationName RHS) {
  if (LHS.getNameKind() != RHS.getNameKind())
    return LHS.getNameKind() < RHS.getNameKind();
  
  switch (LHS.getNameKind()) {
  case DeclarationName::Identifier:
    return LHS.getAsIdentifierInfo()->getName() < 
                                         RHS.getAsIdentifierInfo()->getName();

  case DeclarationName::ObjCZeroArgSelector:
  case DeclarationName::ObjCOneArgSelector:
  case DeclarationName::ObjCMultiArgSelector: {
    Selector LHSSelector = LHS.getObjCSelector();
    Selector RHSSelector = RHS.getObjCSelector();
    for (unsigned I = 0, 
               N = std::min(LHSSelector.getNumArgs(), RHSSelector.getNumArgs());
         I != N; ++I) {
      IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I);
      IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I);
      if (!LHSId || !RHSId)
        return LHSId && !RHSId;
        
      switch (LHSId->getName().compare(RHSId->getName())) {
      case -1: return true;
      case 1: return false;
      default: break;
      }
    }
    
    return LHSSelector.getNumArgs() < RHSSelector.getNumArgs();
  }
  
  case DeclarationName::CXXConstructorName:
  case DeclarationName::CXXDestructorName:
  case DeclarationName::CXXConversionFunctionName:
    return QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType());
              
  case DeclarationName::CXXOperatorName:
    return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator();
              
  case DeclarationName::CXXUsingDirective:
    return false;
  }
              
  return false;
}
Beispiel #5
0
void ODRHash::AddDeclarationName(DeclarationName Name) {
  // Index all DeclarationName and use index numbers to refer to them.
  auto Result = DeclNameMap.insert(std::make_pair(Name, DeclNameMap.size()));
  ID.AddInteger(Result.first->second);
  if (!Result.second) {
    // If found in map, the the DeclarationName has previously been processed.
    return;
  }

  // First time processing each DeclarationName, also process its details.
  AddBoolean(Name.isEmpty());
  if (Name.isEmpty())
    return;

  auto Kind = Name.getNameKind();
  ID.AddInteger(Kind);
  switch (Kind) {
  case DeclarationName::Identifier:
    AddIdentifierInfo(Name.getAsIdentifierInfo());
    break;
  case DeclarationName::ObjCZeroArgSelector:
  case DeclarationName::ObjCOneArgSelector:
  case DeclarationName::ObjCMultiArgSelector: {
    Selector S = Name.getObjCSelector();
    AddBoolean(S.isNull());
    AddBoolean(S.isKeywordSelector());
    AddBoolean(S.isUnarySelector());
    unsigned NumArgs = S.getNumArgs();
    for (unsigned i = 0; i < NumArgs; ++i) {
      AddIdentifierInfo(S.getIdentifierInfoForSlot(i));
    }
    break;
  }
  case DeclarationName::CXXConstructorName:
  case DeclarationName::CXXDestructorName:
    AddQualType(Name.getCXXNameType());
    break;
  case DeclarationName::CXXOperatorName:
    ID.AddInteger(Name.getCXXOverloadedOperator());
    break;
  case DeclarationName::CXXLiteralOperatorName:
    AddIdentifierInfo(Name.getCXXLiteralIdentifier());
    break;
  case DeclarationName::CXXConversionFunctionName:
    AddQualType(Name.getCXXNameType());
    break;
  case DeclarationName::CXXUsingDirective:
    break;
  case DeclarationName::CXXDeductionGuideName: {
    auto *Template = Name.getCXXDeductionGuideTemplate();
    AddBoolean(Template);
    if (Template) {
      AddDecl(Template);
    }
  }
  }
}
Beispiel #6
0
void ODRHash::AddDeclarationName(DeclarationName Name) {
  AddBoolean(Name.isEmpty());
  if (Name.isEmpty())
    return;

  auto Kind = Name.getNameKind();
  ID.AddInteger(Kind);
  switch (Kind) {
  case DeclarationName::Identifier:
    AddIdentifierInfo(Name.getAsIdentifierInfo());
    break;
  case DeclarationName::ObjCZeroArgSelector:
  case DeclarationName::ObjCOneArgSelector:
  case DeclarationName::ObjCMultiArgSelector: {
    Selector S = Name.getObjCSelector();
    AddBoolean(S.isNull());
    AddBoolean(S.isKeywordSelector());
    AddBoolean(S.isUnarySelector());
    unsigned NumArgs = S.getNumArgs();
    for (unsigned i = 0; i < NumArgs; ++i) {
      AddIdentifierInfo(S.getIdentifierInfoForSlot(i));
    }
    break;
  }
  case DeclarationName::CXXConstructorName:
  case DeclarationName::CXXDestructorName:
    AddQualType(Name.getCXXNameType());
    break;
  case DeclarationName::CXXOperatorName:
    ID.AddInteger(Name.getCXXOverloadedOperator());
    break;
  case DeclarationName::CXXLiteralOperatorName:
    AddIdentifierInfo(Name.getCXXLiteralIdentifier());
    break;
  case DeclarationName::CXXConversionFunctionName:
    AddQualType(Name.getCXXNameType());
    break;
  case DeclarationName::CXXUsingDirective:
    break;
  case DeclarationName::CXXDeductionGuideName: {
    auto *Template = Name.getCXXDeductionGuideTemplate();
    AddBoolean(Template);
    if (Template) {
      AddDecl(Template);
    }
  }
  }
}
Beispiel #7
0
// The core lookup interface.
DeclContext::lookup_result ClangASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) {
    switch (Name.getNameKind()) {
    // Normal identifiers.
    case DeclarationName::Identifier:
      break;
            
    // Operator names.  Not important for now.
    case DeclarationName::CXXOperatorName:
    case DeclarationName::CXXLiteralOperatorName:
      return DeclContext::lookup_result();
            
    // Using directives found in this context.
    // Tell Sema we didn't find any or we'll end up getting asked a *lot*.
    case DeclarationName::CXXUsingDirective:
      return SetNoExternalVisibleDeclsForName(DC, Name);
            
    // These aren't looked up like this.
    case DeclarationName::ObjCZeroArgSelector:
    case DeclarationName::ObjCOneArgSelector:
    case DeclarationName::ObjCMultiArgSelector:
      return DeclContext::lookup_result();

    // These aren't possible in the global context.
    case DeclarationName::CXXConstructorName:
    case DeclarationName::CXXDestructorName:
    case DeclarationName::CXXConversionFunctionName:
      return DeclContext::lookup_result();
    }
    
	llvm::SmallVector<NamedDecl*, 4> Decls;
    
    NameSearchContext NSC(*this, Decls, Name, DC);
    
    DeclMap.GetDecls(NSC, Name.getAsString().c_str());
    return SetExternalVisibleDeclsForName(DC, Name, Decls);
}
void RemoveUnusedFunction::handleOneUnresolvedLookupExpr(
       const FunctionDecl *CurrentFD,
       const UnresolvedLookupExpr *E)
{
  DeclarationName DName = E->getName();
  DeclarationName::NameKind K = DName.getNameKind();
  if ((K != DeclarationName::CXXOperatorName) &&
      (K != DeclarationName::Identifier))
    return;
  const NestedNameSpecifier *NNS = E->getQualifier();
  // we fail only if UE is invoked with some qualifier or 
  // instantiation, e.g.:
  // namespace NS { template<typename T> void foo(T&) { } }
  // template<typename T> void bar(T p) { NS::foo(p); } 
  // removing foo would fail. 
  // 
  // template <typename T> void foo() { }
  // template <typename T> void bar() { foo<T>(); }
  // removing foo would faill, too
  // 
  // On the other handle, the following code is ok:
  // template<typename T> void foo(T&) { }
  // template<typename T> void bar(T p) { foo(p); } 
  const FunctionDecl *FD = NULL;
  if (NNS) {
    FD = getFunctionDeclFromSpecifier(DName, NNS);
  }
  else {
    const DeclContext *Ctx = CurrentFD->getLookupParent();
    FD = lookupFunctionDeclShallow(DName, Ctx);
  }
  
  if (!FD || FD->isReferenced())
    return;
  addOneReferencedFunction(FD);
}
Beispiel #9
0
bool RewriteUtils::replaceFunctionDeclName(const FunctionDecl *FD,
                                      const std::string &NameStr)
{
  // We cannot naively use FD->getNameAsString() here. 
  // For example, for a template class
  // template<typename T>
  // class SomeClass {
  // public:
  //   SomeClass() {}
  // };
  // applying getNameAsString() on SomeClass() gives us SomeClass<T>.

  DeclarationNameInfo NameInfo = FD->getNameInfo();
  DeclarationName DeclName = NameInfo.getName();
  DeclarationName::NameKind K = DeclName.getNameKind();
  TransAssert((K != DeclarationName::CXXDestructorName) &&
              "Cannot rename CXXDestructorName here!");

  std::string FDName = FD->getNameAsString();
  size_t FDNameLen = FD->getNameAsString().length();
  if (K == DeclarationName::CXXConstructorName) {
    const Type *Ty = DeclName.getCXXNameType().getTypePtr();
    if (Ty->getTypeClass() == Type::InjectedClassName) {
      const CXXRecordDecl *CXXRD = Ty->getAsCXXRecordDecl();
      std::string RDName = CXXRD->getNameAsString();
      FDNameLen = FDName.find(RDName);
      TransAssert((FDNameLen != std::string::npos) && 
                  "Cannot find RecordDecl Name!");
      FDNameLen += RDName.length();
    }
  }

  return !TheRewriter->ReplaceText(NameInfo.getLoc(),
                                   FDNameLen,
                                   NameStr);
}
Beispiel #10
0
void
MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
                                               DeclarationName Name) {
  //  <unqualified-name> ::= <operator-name>
  //                     ::= <ctor-dtor-name>
  //                     ::= <source-name>
  switch (Name.getNameKind()) {
    case DeclarationName::Identifier: {
      if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
        mangleSourceName(II);
        break;
      }
      
      // Otherwise, an anonymous entity.  We must have a declaration.
      assert(ND && "mangling empty name without declaration");
      
      if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
        if (NS->isAnonymousNamespace()) {
          Out << "?A";
          break;
        }
      }
      
      // We must have an anonymous struct.
      const TagDecl *TD = cast<TagDecl>(ND);
      if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) {
        assert(TD->getDeclContext() == D->getDeclContext() &&
               "Typedef should not be in another decl context!");
        assert(D->getDeclName().getAsIdentifierInfo() &&
               "Typedef was not named!");
        mangleSourceName(D->getDeclName().getAsIdentifierInfo());
        break;
      }

      // When VC encounters an anonymous type with no tag and no typedef,
      // it literally emits '<unnamed-tag>'.
      Out << "<unnamed-tag>";
      break;
    }
      
    case DeclarationName::ObjCZeroArgSelector:
    case DeclarationName::ObjCOneArgSelector:
    case DeclarationName::ObjCMultiArgSelector:
      assert(false && "Can't mangle Objective-C selector names here!");
      break;
      
    case DeclarationName::CXXConstructorName:
      assert(false && "Can't mangle constructors yet!");
      break;
      
    case DeclarationName::CXXDestructorName:
      assert(false && "Can't mangle destructors yet!");
      break;
      
    case DeclarationName::CXXConversionFunctionName:
      // <operator-name> ::= ?B # (cast)
      // The target type is encoded as the return type.
      Out << "?B";
      break;
      
    case DeclarationName::CXXOperatorName:
      mangleOperatorName(Name.getCXXOverloadedOperator());
      break;
      
    case DeclarationName::CXXLiteralOperatorName:
      // FIXME: Was this added in VS2010? Does MS even know how to mangle this?
      assert(false && "Don't know how to mangle literal operators yet!");
      break;
      
    case DeclarationName::CXXUsingDirective:
      assert(false && "Can't mangle a using directive name!");
      break;
  }
}
void RemoveNestedFunction::getNewTmpVariableStr(ASTContext &ASTCtx,
                                                std::string &VarStr)
{
  std::stringstream SS;
  unsigned int NamePostfix = NameQueryWrap->getMaxNamePostfix();

  SS << RewriteHelper->getTmpVarNamePrefix() << (NamePostfix + 1);
  VarStr = SS.str();
  setTmpVarName(VarStr);

  QualType QT;
  const Expr *E = TheCallExpr->getCallee();

  if (const UnresolvedLookupExpr *UE = dyn_cast<UnresolvedLookupExpr>(E)) {
    // clang doesn't always resolve CallExpr's callee. For example:
    //   template<typename T> int foo1(int p) {return p;}
    //   template<typename T> int foo2(int p) {return p;}
    //   template<typename T>
    //   void bar(void) { foo1<T>(foo2<T>(1)); }
    // foo2<T>(1) has BuiltinType and hence
    // TheCallExpr->getCallReturnType() will segfault.
    // In this case, we have to lookup a corresponding function decl

    DeclarationName DName = UE->getName();
    TransAssert(((DName.getNameKind() == DeclarationName::Identifier) ||
                 (DName.getNameKind() == DeclarationName::CXXOperatorName)) &&
                "Not an indentifier!");
    const FunctionDecl *FD = NULL;
    if (const NestedNameSpecifier *NNS = UE->getQualifier()) {
      if (const DeclContext *Ctx = getDeclContextFromSpecifier(NNS)) {
        DeclContextSet VisitedCtxs;
        FD = lookupFunctionDecl(DName, Ctx, VisitedCtxs);
      }
    }
    if (!FD) {
      DeclContextSet VisitedCtxs;
      FD =
        lookupFunctionDecl(DName, TheFuncDecl->getLookupParent(), VisitedCtxs);
    }
    // give up and generate a tmp var of int type, e.g.:
    // template <class T> struct S {
    //   T x;
    //   template <class A> void foo(A &a0) { x(y(a0)); }
    // };
    if (!FD)
      return getNewIntTmpVariable(VarStr);

    QT = FD->getReturnType();
    //FIXME: This is actually not quite correct, we should get the instantiated
    // type here.
    return getNewTmpVariable(QT, VarStr);
  }

  if (const UnresolvedMemberExpr *UM = dyn_cast<UnresolvedMemberExpr>(E)) {
    DeclarationName DName = UM->getMemberName();
    CXXRecordDecl *CXXRD = UM->getNamingClass();
    DeclContextSet VisitedCtxs;
    const FunctionDecl *FD = lookupFunctionDecl(DName, CXXRD, VisitedCtxs);
    // FIXME: try to resolve FD here
    if (FD)
      QT = FD->getReturnType();
    return getNewTmpVariable(QT, VarStr);
  }

  if (const CXXTemporaryObjectExpr *CXXTE =
      dyn_cast<CXXTemporaryObjectExpr>(E)) {
    const CXXConstructorDecl *CXXCtor = CXXTE->getConstructor();
    QT = CXXCtor->getThisType(ASTCtx);
    return getNewTmpVariable(QT, VarStr);
  }

  if (const CXXTemporaryObjectExpr *CXXTE =
      dyn_cast<CXXTemporaryObjectExpr>(E)) {
    const CXXConstructorDecl *CXXCtor = CXXTE->getConstructor();
    QT = CXXCtor->getThisType(ASTCtx);
    return getNewTmpVariable(QT, VarStr);
  }

  if (const CXXDependentScopeMemberExpr *ME =
      dyn_cast<CXXDependentScopeMemberExpr>(E)) {

    if (ME->isImplicitAccess())
      return;
    DeclarationName DName = ME->getMember();
    TransAssert((DName.getNameKind() == DeclarationName::Identifier) &&
                "Not an indentifier!");
    const Expr *E = ME->getBase();
    TransAssert(E && "NULL Base Expr!");
    const Expr *BaseE = E->IgnoreParens();

    // handle cases where base expr or member name is dependent, e.g.,
    // template<typename T>
    // class S {
    //   int f1(int p1) { return p1; };
    //   int f2(int p2) { return p2; };
    //   void f3(void);
    // };
    // template<typename T>
    // void S<T>::f3(void)
    // {
    //   f1(this->f2(1));
    // }
    // where this->f2(1) is a CXXDependentScopeMemberExpr
    if (dyn_cast<CXXThisExpr>(BaseE)) {
      const DeclContext *Ctx = TheFuncDecl->getLookupParent();
      TransAssert(Ctx && "Bad DeclContext!");
      DeclContextSet VisitedCtxs;
      const FunctionDecl *FD = lookupFunctionDecl(DName, Ctx, VisitedCtxs);
      TransAssert(FD && "Cannot resolve DName!");
      QT = FD->getReturnType();
      return getNewTmpVariable(QT, VarStr);
    }

    // handle other cases where lookupDeclContext is different from
    // the current CXXRecord, e.g.,
    const Type *Ty = ME->getBaseType().getTypePtr();
    if (const DeclContext *Ctx = getBaseDeclFromType(Ty)) {
      DeclContextSet VisitedCtxs;
      const FunctionDecl *FD = lookupFunctionDecl(DName, Ctx, VisitedCtxs);
      if (!FD) {
        return getNewTmpVariable(QT, VarStr);
      }
      QT = FD->getReturnType();
      const Type *RVTy = QT.getTypePtr();
      if (RVTy->getAs<InjectedClassNameType>()) {
        // handle cases like:
        // template <typename> struct D {
        //   D f();
        // };
        // template <typename T> void foo(D<T>);
        // template <typename T > void bar () {
        //   D<T> G;
        //   foo(G.f());
        // }
        // in this case, seems it's hard to retrieve the instantiated type
        // of f's return type, because `D<T> G' is dependent. I tried
        // findSpecialization from ClassTemplateDecl, but it didn't work.
        // So use a really ugly way, i.e., manipulating strings...
        const TemplateSpecializationType *TST =
          Ty->getAs<TemplateSpecializationType>();
        TransAssert(TST && "Invalid TemplateSpecialization Type!");

        QT.getAsStringInternal(VarStr,
                               Context->getPrintingPolicy());
        return getVarStrForTemplateSpecialization(VarStr, TST);
      }
      else {
        // other cases:
        // template <typename> struct D {
        //   int f();
        // };
        // void foo(int);
        // template <typename T > void bar () {
        //   D<T> G;
        //   foo(G.f());
        // }
        return getNewTmpVariable(QT, VarStr);
      }
    }
    else {
      // template <typename> struct D {
      // D f();
      // D operator[] (int);
      // };
      // template <typename T> void foo(D<T>);
      // template <typename T > void bar () {
      //   D<T> G;
      //   foo(G[0].f());
      // }
      // In this case, G[0] is of BuiltinType.
      // But why does clang represent a dependent type as BuiltinType here?

      TransAssert((Ty->getAs<BuiltinType>() ||
                   Ty->getAs<TemplateTypeParmType>() ||
                   Ty->getAs<TypedefType>() ||
                   Ty->getAs<DependentNameType>())
                  && "Uncaught Type");
      // FIXME: This is incorrect!
      // a couple of questions
      //  - how can we find a correct DeclContext where we could lookup f?
      //  - can we obtain the dependent template argument from BuiltinType?
      // Probably we cannot do these? Comments from lib/AST/ASTContext.cpp:
      //
      // Placeholder type for type-dependent expressions whose type is
      // completely unknown. No code should ever check a type against
      // DependentTy and users should never see it; however, it is here to
      // help diagnose failures to properly check for type-dependent
      // expressions.
      return getNewIntTmpVariable(VarStr);
    }
  }

  const Type *CalleeType = E->getType().getTypePtr();
  // template <class T1, class T2> struct S {
  //   T1 x; T2 y;
  //   template <class A> void foo(A &a0) { x(y(a0)); }
  // };
  if (const TemplateTypeParmType *PT =
      dyn_cast<TemplateTypeParmType>(CalleeType)) {
    const TemplateTypeParmDecl *PD = PT->getDecl();
    std::string DStr = PD->getNameAsString();
    VarStr = DStr + " " + VarStr;
    return;
  }
  QT = TheCallExpr->getCallReturnType(ASTCtx);
  getNewTmpVariable(
    QT.getTypePtr()->getUnqualifiedDesugaredType()->getCanonicalTypeInternal(),
    VarStr);
}