Пример #1
0
bool LToGASTVisitor::makeLocalAsGlobalVar(FunctionDecl *FD,
                                          VarDecl *LV)
{
  std::string GlobalVarStr;
  std::string NewName = ConsumerInstance->getNewName();

  QualType T = LV->getType();
  T.getAsStringInternal(NewName, 
                        ConsumerInstance->Context->getPrintingPolicy());

  GlobalVarStr = NewName;

  if (LV->hasInit()) {
    const Expr *InitExpr = LV->getInit();
    std::string InitStr("");
    ConsumerInstance->RewriteHelper->getExprString(InitExpr, 
                                                   InitStr);
    GlobalVarStr += " = ";
    GlobalVarStr += InitStr; 
  }

  GlobalVarStr += ";\n";

  return ConsumerInstance->RewriteHelper->
           insertStringBeforeFunc(FD, GlobalVarStr);
}
Пример #2
0
void CallExprToValue::replaceCallExpr(void)
{
  std::string CommaStr = "";

  QualType RVQualType = TheCallExpr->getType();
  const Type *RVType = RVQualType.getTypePtr();
  if (RVType->isVoidType()) {
    // Nothing to do
  }
  else if (RVType->isUnionType() || RVType->isStructureType()) {
    std::string RVStr("");
    RewriteHelper->getTmpTransName(NamePostfix, RVStr);
    NamePostfix++;

    CommaStr = RVStr;
    RVQualType.getAsStringInternal(RVStr, Context->getPrintingPolicy());
    RVStr += ";\n";
    RewriteHelper->insertStringBeforeFunc(CurrentFD, RVStr);
  }
  else {
    CommaStr = "0";
  }

  RewriteHelper->replaceExpr(TheCallExpr, CommaStr);
}
bool InstantiateTemplateParam::getTypeString(
       const QualType &QT, std::string &Str, std::string &ForwardStr)
{
  const Type *Ty = QT.getTypePtr();
  Type::TypeClass TC = Ty->getTypeClass();

  switch (TC) {
  case Type::Elaborated: {
    const ElaboratedType *ETy = dyn_cast<ElaboratedType>(Ty);
    return getTypeString(ETy->getNamedType(), Str, ForwardStr);
  }

  case Type::Typedef: {
    const TypedefType *TdefTy = dyn_cast<TypedefType>(Ty);
    const TypedefNameDecl *TdefD = TdefTy->getDecl();
    return getTypeString(TdefD->getUnderlyingType(), Str, ForwardStr);
  }

  case Type::Record: {
    RecordDeclSet TempAvailableRecordDecls;
    getForwardDeclStr(Ty, ForwardStr, TempAvailableRecordDecls);
    QT.getAsStringInternal(Str, Context->getPrintingPolicy());
    return true;
  }

  case Type::Builtin: {
    QT.getAsStringInternal(Str, Context->getPrintingPolicy());
    return true;
  }

  default:
    return false;
  }

  TransAssert(0 && "Unreachable code!");
  return false;
}
Пример #4
0
bool BinOpSimplification::addNewTmpVariable(void)
{
  QualType QT = TheBinOp->getType();
  std::string VarStr;
  std::stringstream SS;
  unsigned int NamePostfix = NameQueryWrap->getMaxNamePostfix();

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

  QT.getAsStringInternal(VarStr,
                         Context->getPrintingPolicy());

  VarStr += ";";
  return RewriteHelper->addLocalVarToFunc(VarStr, TheFuncDecl);
}
Пример #5
0
void SimplifyCallExpr::replaceCallExpr(void)
{
  std::string CommaStr("");
  unsigned int NumArg = TheCallExpr->getNumArgs();
  if (NumArg == 0) {
    RewriteHelper->replaceExpr(TheCallExpr, CommaStr);
    return;
  }

  const Expr *Arg = TheCallExpr->getArg(0);
  std::string ArgStr;
  handleOneArgStr(Arg, ArgStr);
  CommaStr += ("(" + ArgStr);

  for (unsigned int I = 1; I < NumArg; ++I) {
    Arg = TheCallExpr->getArg(I);
    handleOneArgStr(Arg, ArgStr);
    CommaStr += ("," + ArgStr);
  }

  QualType RVQualType = TheCallExpr->getType();
  const Type *RVType = RVQualType.getTypePtr();
  if (RVType->isVoidType()) {
    // Nothing to do
  }
  else if (RVType->isUnionType() || RVType->isStructureType()) {
    std::string RVStr("");
    RewriteHelper->getTmpTransName(NamePostfix, RVStr);
    NamePostfix++;

    CommaStr += ("," + RVStr);
    RVQualType.getAsStringInternal(RVStr, Context->getPrintingPolicy());
    RVStr += ";\n";
    RewriteHelper->insertStringBeforeFunc(CurrentFD, RVStr);
  }
  else {
    CommaStr += ",0";
  }

  CommaStr += ")";
  RewriteHelper->replaceExpr(TheCallExpr, CommaStr);
}
Пример #6
0
bool AggregateToScalar::addTmpVar(const Expr *RefE,
                                  const std::string &VarName,
                                  const std::string *InitStr)
{
  std::string VarStr(VarName);
  QualType QT = RefE->getType();
  QT.getAsStringInternal(VarStr, Context->getPrintingPolicy());

  if (InitStr) {
    VarStr += " = ";
    VarStr += (*InitStr);
  }
  VarStr += ";";
   
  if (TheVarDecl->getStorageClass() == SC_Static)
    VarStr = "static " + VarStr; 

  TransAssert(!dyn_cast<ParmVarDecl>(TheVarDecl) && 
              "We don't handle ParmVarDecl!");
  if (TheVarDecl->isLocalVarDecl()) {
    DeclStmt *TheDeclStmt = VarDeclToDeclStmtMap[TheVarDecl];
    TransAssert(TheDeclStmt && "NULL TheDeclStmt");
    return RewriteHelper->addStringAfterStmt(TheDeclStmt, VarStr);
  }
  else {
    llvm::DenseMap<const VarDecl *, DeclGroupRef>::iterator DI =
      VarDeclToDeclGroupMap.find(TheVarDecl);
    TransAssert((DI != VarDeclToDeclGroupMap.end()) && 
                 "Cannot find VarDeclGroup!");
    VarDecl *LastVD = NULL;
    DeclGroupRef DR = (*DI).second;
    for (DeclGroupRef::iterator I = DR.begin(), E = DR.end(); I != E; ++I) {
      LastVD = dyn_cast<VarDecl>(*I);
    }
    TransAssert(LastVD && "Bad LastVD!");
    return RewriteHelper->addStringAfterVarDecl(LastVD, VarStr);
  }
}
Пример #7
0
  ASTNodeInfo EvaluateTSynthesizer::VisitDeclStmt(DeclStmt* Node) {
    // Visit all the children, which are the contents of the DeclGroupRef
    for (Stmt::child_iterator
           I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
      if (*I) {
        Expr* E = cast_or_null<Expr>(*I);
        if (!E || !IsArtificiallyDependent(E))
          continue;
        //FIXME: don't assume there is only one decl.
        assert(Node->isSingleDecl() && "There is more that one decl in stmt");
        VarDecl* CuredDecl = cast_or_null<VarDecl>(Node->getSingleDecl());
        assert(CuredDecl && "Not a variable declaration!");
        QualType CuredDeclTy = CuredDecl->getType();
        // check if the case is sometype * somevar = init;
        // or some_builtin_type somevar = init;
        if (CuredDecl->hasInit() && (CuredDeclTy->isAnyPointerType()
                                     || !CuredDeclTy->isRecordType())) {
          *I = SubstituteUnknownSymbol(CuredDeclTy, CuredDecl->getInit());
          continue;
        }

        // 1. Check whether this is the case of MyClass A(dep->symbol())
        // 2. Insert the RuntimeUniverse's LifetimeHandler instance
        // 3. Change the A's initializer to *(MyClass*)instance.getMemory()
        // 4. Make A reference (&A)
        // 5. Set the new initializer of A
        if (CuredDeclTy->isLValueReferenceType())
          continue;

        // Set Sema's Current DeclContext to the one we need
        DeclContext* OldDC = m_Sema->CurContext;
        m_Sema->CurContext = CuredDecl->getDeclContext();

        ASTNodeInfo NewNode;
        // 2.1 Get unique name for the LifetimeHandler instance and
        // initialize it
        std::string UniqueName;
        createUniqueName(UniqueName);
        IdentifierInfo& II = m_Context->Idents.get(UniqueName);

        // Prepare the initialization Exprs.
        // We want to call LifetimeHandler(DynamicExprInfo* ExprInfo,
        //                                 DeclContext DC,
        //                                 const char* type)
        //                                 Interpreter* interp)
        llvm::SmallVector<Expr*, 4> Inits;
        // Add MyClass in LifetimeHandler unique(DynamicExprInfo* ExprInfo
        //                                       DC,
        //                                       "MyClass"
        //                                       Interpreter* Interp)
        // Build Arg0 DynamicExprInfo
        Inits.push_back(BuildDynamicExprInfo(E));
        // Build Arg1 DeclContext* DC
        QualType DCTy = m_Context->getTypeDeclType(m_DeclContextDecl);
        Inits.push_back(utils::Synthesize::CStyleCastPtrExpr(m_Sema, DCTy,
                                                     (uint64_t)m_CurDeclContext)
                        );
        // Build Arg2 llvm::StringRef
        // Get the type of the type without specifiers
        PrintingPolicy Policy(m_Context->getLangOpts());
        Policy.SuppressTagKeyword = 1;
        std::string Res;
        CuredDeclTy.getAsStringInternal(Res, Policy);
        Inits.push_back(ConstructConstCharPtrExpr(Res.c_str()));

        // Build Arg3 cling::Interpreter
        CXXScopeSpec CXXSS;
        DeclarationNameInfo NameInfo(m_gCling->getDeclName(), 
                                     m_gCling->getLocStart());
        Expr* gClingDRE 
          = m_Sema->BuildDeclarationNameExpr(CXXSS, NameInfo ,m_gCling).take();
        Inits.push_back(gClingDRE);
        
        // 2.3 Create a variable from LifetimeHandler.
        QualType HandlerTy = m_Context->getTypeDeclType(m_LifetimeHandlerDecl);
        TypeSourceInfo* TSI = m_Context->getTrivialTypeSourceInfo(HandlerTy,
                                                                  m_NoSLoc);
        VarDecl* HandlerInstance = VarDecl::Create(*m_Context,
                                                   CuredDecl->getDeclContext(),
                                                   m_NoSLoc,
                                                   m_NoSLoc,
                                                   &II,
                                                   HandlerTy,
                                                   TSI,
                                                   SC_None);
        
        // 2.4 Call the best-match constructor. The method does overload
        // resolution of the constructors and then initializes the new
        // variable with it
        ExprResult InitExprResult
          = m_Sema->ActOnParenListExpr(m_NoSLoc,
                                       m_NoELoc,
                                       Inits);
        m_Sema->AddInitializerToDecl(HandlerInstance,
                                     InitExprResult.take(),
                                     /*DirectInit*/ true,
                                     /*TypeMayContainAuto*/ false);
        
        // 2.5 Register the instance in the enclosing context
        CuredDecl->getDeclContext()->addDecl(HandlerInstance);
        NewNode.addNode(new (m_Context)
                        DeclStmt(DeclGroupRef(HandlerInstance),
                                 m_NoSLoc,
                                 m_NoELoc)
                        );
        
        // 3.1 Build a DeclRefExpr, which holds the object
        DeclRefExpr* MemberExprBase
          = m_Sema->BuildDeclRefExpr(HandlerInstance,
                                     HandlerTy,
                                     VK_LValue,
                                     m_NoSLoc
                                     ).takeAs<DeclRefExpr>();
        // 3.2 Create a MemberExpr to getMemory from its declaration.
        CXXScopeSpec SS;
        LookupResult MemberLookup(*m_Sema, m_LHgetMemoryDecl->getDeclName(),
                                  m_NoSLoc, Sema::LookupMemberName);
        // Add the declaration as if doesn't exist.
        // TODO: Check whether this is the most appropriate variant
        MemberLookup.addDecl(m_LHgetMemoryDecl, AS_public);
        MemberLookup.resolveKind();
        Expr* MemberExpr = m_Sema->BuildMemberReferenceExpr(MemberExprBase,
                                                            HandlerTy,
                                                            m_NoSLoc,
                                                            /*IsArrow=*/false,
                                                            SS,
                                                            m_NoSLoc,
                                                     /*FirstQualifierInScope=*/0,
                                                            MemberLookup,
                                                            /*TemplateArgs=*/0
                                                            ).take();
        // 3.3 Build the actual call
        Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext);
        Expr* theCall = m_Sema->ActOnCallExpr(S,
                                              MemberExpr,
                                              m_NoSLoc,
                                              MultiExprArg(),
                                              m_NoELoc).take();
        // Cast to the type LHS type
        Expr* Result 
          = utils::Synthesize::CStyleCastPtrExpr(m_Sema, CuredDeclTy, theCall);
        // Cast once more (dereference the cstyle cast)
        Result = m_Sema->BuildUnaryOp(S, m_NoSLoc, UO_Deref, Result).take();
        // 4.
        CuredDecl->setType(m_Context->getLValueReferenceType(CuredDeclTy));
        // 5.
        CuredDecl->setInit(Result);

        NewNode.addNode(Node);

        // Restore Sema's original DeclContext
        m_Sema->CurContext = OldDC;
        return NewNode;
      }
    }
    return ASTNodeInfo(Node, 0);
  }
Пример #8
0
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);
}
Пример #9
0
void RemoveNestedFunction::getNewTmpVariable(const QualType &QT,
                                             std::string &VarStr)
{
  QT.getAsStringInternal(VarStr, Context->getPrintingPolicy());
}