Example #1
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);
  }
Example #2
0
  Expr* EvaluateTSynthesizer::BuildDynamicExprInfo(Expr* SubTree,
                                                   bool ValuePrinterReq) {
    // We need to evaluate it in its own context. Evaluation on the global
    // scope per se can break for example the compound literals, which have
    // to be constants (see [C99 6.5.2.5])
    Sema::ContextRAII pushedDC(*m_Sema, m_CurDeclContext);

    // 1. Get the expression containing @-s and get the variable addresses
    std::string Template;
    llvm::SmallVector<DeclRefExpr*, 4> Addresses;
    llvm::raw_string_ostream OS(Template);
    const PrintingPolicy& Policy = m_Context->getPrintingPolicy();

    StmtPrinterHelper helper(Policy, Addresses, m_Sema);
    // In case when we print non paren inits like int i = h->Draw();
    // not int i(h->Draw()). This simplifies the LifetimeHandler's
    // constructor, there we don't need to add parenthesis while
    // wrapping the expression.
    if (!isa<ParenListExpr>(SubTree))
      OS << '(';
    SubTree->printPretty(OS, &helper, Policy);
    if (!isa<ParenListExpr>(SubTree))
      OS << ')';

    OS.flush();

    // 2. Build the template
    Expr* ExprTemplate = ConstructConstCharPtrExpr(Template.c_str());

    // 3. Build the array of addresses
    QualType VarAddrTy = m_Sema->BuildArrayType(m_Context->VoidPtrTy,
                                                ArrayType::Normal,
                                                /*ArraySize*/0,
                                                /*IndexTypeQuals*/0,
                                                m_NoRange,
                                                DeclarationName() );

    llvm::SmallVector<Expr*, 2> Inits;
    Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext);
    for (unsigned int i = 0; i < Addresses.size(); ++i) {

      Expr* UnOp
        = m_Sema->BuildUnaryOp(S, m_NoSLoc, UO_AddrOf, Addresses[i]).take();
      m_Sema->ImpCastExprToType(UnOp,
                                m_Context->getPointerType(m_Context->VoidPtrTy),
                                CK_BitCast);
      Inits.push_back(UnOp);
    }

    // We need valid source locations to avoid assert(InitList.isExplicit()...)
    InitListExpr* ILE = m_Sema->ActOnInitList(m_NoSLoc,
                                              Inits,
                                              m_NoELoc).takeAs<InitListExpr>();
    TypeSourceInfo* TSI 
      = m_Context->getTrivialTypeSourceInfo(VarAddrTy, m_NoSLoc);
    Expr* ExprAddresses = m_Sema->BuildCompoundLiteralExpr(m_NoSLoc,
                                                           TSI,
                                                           m_NoELoc,
                                                           ILE).take();
    assert (ExprAddresses && "Could not build the void* array");
    m_Sema->ImpCastExprToType(ExprAddresses,
                              m_Context->getPointerType(m_Context->VoidPtrTy),
                              CK_ArrayToPointerDecay);

    // Is the result of the expression to be printed or not
    Expr* VPReq = 0;
    if (ValuePrinterReq)
      VPReq = m_Sema->ActOnCXXBoolLiteral(m_NoSLoc, tok::kw_true).take();
    else
      VPReq = m_Sema->ActOnCXXBoolLiteral(m_NoSLoc, tok::kw_false).take();

    llvm::SmallVector<Expr*, 4> CtorArgs;
    CtorArgs.push_back(ExprTemplate);
    CtorArgs.push_back(ExprAddresses);
    CtorArgs.push_back(VPReq);

    // 4. Call the constructor
    QualType ExprInfoTy = m_Context->getTypeDeclType(m_DynamicExprInfoDecl);
    ExprResult Initializer = m_Sema->ActOnParenListExpr(m_NoSLoc, m_NoELoc,
                                                        CtorArgs);
    TypeSourceInfo* TrivialTSI 
      = m_Context->getTrivialTypeSourceInfo(ExprInfoTy, SourceLocation());
    Expr* Result = m_Sema->BuildCXXNew(m_NoSLoc,
                                       /*UseGlobal=*/false,
                                       m_NoSLoc,
                                       /*PlacementArgs=*/MultiExprArg(),
                                       m_NoELoc,
                                       m_NoRange,
                                       ExprInfoTy,
                                       TrivialTSI,
                                       /*ArraySize=*/0,
                                       //BuildCXXNew depends on the SLoc to be
                                       //valid!
                                       // TODO: Propose a patch in clang
                                       m_NoRange,
                                       Initializer.take(),
                                       /*TypeMayContainAuto*/false
                                       ).take();
    return Result;
  }
  Expr* EvaluateTSynthesizer::BuildDynamicExprInfo(Expr* SubTree,
                                                   bool ValuePrinterReq) {
    // 1. Find the DynamicExprInfo class
    CXXRecordDecl* ExprInfo
      = cast_or_null<CXXRecordDecl>(m_Interpreter->LookupDecl("cling").
                                    LookupDecl("DynamicExprInfo").
                                    getSingleDecl());
    assert(ExprInfo && "DynamicExprInfo declaration not found!");

    // 2. Get the expression containing @-s and get the variable addresses
    std::string Template;
    llvm::SmallVector<DeclRefExpr*, 4> Addresses;
    llvm::raw_string_ostream OS(Template);
    const PrintingPolicy& Policy = m_Context->getPrintingPolicy();

    StmtPrinterHelper helper(Policy, Addresses, m_Sema);
    // In case when we print non paren inits like int i = h->Draw();
    // not int i(h->Draw()). This simplifies the LifetimeHandler's
    // constructor, there we don't need to add parenthesis while
    // wrapping the expression.
    if (!isa<ParenListExpr>(SubTree))
      OS << '(';
    SubTree->printPretty(OS, &helper, Policy);
    if (!isa<ParenListExpr>(SubTree))
      OS << ')';

    OS.flush();

    // 3. Build the template
    Expr* ExprTemplate = ConstructConstCharPtrExpr(Template.c_str());

    // 4. Build the array of addresses
    QualType VarAddrTy = m_Sema->BuildArrayType(m_Context->VoidPtrTy,
                                                ArrayType::Normal,
                                                /*ArraySize*/0,
                                                Qualifiers(),
                                                m_NoRange,
                                                DeclarationName() );

    ASTOwningVector<Expr*> Inits(*m_Sema);
    Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext);
    for (unsigned int i = 0; i < Addresses.size(); ++i) {

      Expr* UnOp
        = m_Sema->BuildUnaryOp(S, m_NoSLoc, UO_AddrOf, Addresses[i]).take();
      m_Sema->ImpCastExprToType(UnOp,
                                m_Context->getPointerType(m_Context->VoidPtrTy),
                                CK_BitCast);
      Inits.push_back(UnOp);
    }

    // We need valid source locations to avoid assert(InitList.isExplicit()...)
    InitListExpr* ILE = m_Sema->ActOnInitList(m_NoSLoc,
                                              move_arg(Inits),
                                              m_NoELoc).takeAs<InitListExpr>();
    Expr* ExprAddresses = m_Sema->BuildCompoundLiteralExpr(m_NoSLoc,
                                     m_Context->CreateTypeSourceInfo(VarAddrTy),
                                                           m_NoELoc,
                                                           ILE).take();
    assert (ExprAddresses && "Could not build the void* array");
    m_Sema->ImpCastExprToType(ExprAddresses,
                              m_Context->getPointerType(m_Context->VoidPtrTy),
                              CK_ArrayToPointerDecay);

    // Is the result of the expression to be printed or not
    Expr* VPReq = 0;
    if (ValuePrinterReq)
      VPReq = m_Sema->ActOnCXXBoolLiteral(m_NoSLoc, tok::kw_true).take();
    else
      VPReq = m_Sema->ActOnCXXBoolLiteral(m_NoSLoc, tok::kw_false).take();

    ASTOwningVector<Expr*> CtorArgs(*m_Sema);
    CtorArgs.push_back(ExprTemplate);
    CtorArgs.push_back(ExprAddresses);
    CtorArgs.push_back(VPReq);

    // 5. Call the constructor
    QualType ExprInfoTy = m_Context->getTypeDeclType(ExprInfo);
    ExprResult Initializer = m_Sema->ActOnParenListExpr(m_NoSLoc, m_NoELoc,
                                                        move_arg(CtorArgs));
    Expr* Result = m_Sema->BuildCXXNew(m_NoSLoc,
                                       /*UseGlobal=*/false,
                                       m_NoSLoc,
                                       /*PlacementArgs=*/MultiExprArg(),
                                       m_NoELoc,
                                       m_NoRange,
                                       ExprInfoTy,
                                    m_Context->CreateTypeSourceInfo(ExprInfoTy),
                                       /*ArraySize=*/0,
                                       //BuildCXXNew depends on the SLoc to be
                                       //valid!
                                       // TODO: Propose a patch in clang
                                       m_NoRange,
                                       Initializer.take(),
                                       /*TypeMayContainAuto*/false
                                       ).take();
    return Result;
  }