// If the dynamic expression is in the conditional clause of the if
  // assume that the return type is bool, because we know that
  // everything in the condition of IfStmt is implicitly converted into bool
  ASTNodeInfo EvaluateTSynthesizer::VisitIfStmt(IfStmt* Node) {

    // See whether there is var defined. Eg: if (int i = f->call())
    // It will fall into DeclStmt.
    if (Node->getConditionVariableDeclStmt()) {
      // Removing the const, which shouldn't be dangerous
      VisitDeclStmt(const_cast<DeclStmt*>(
                                         Node->getConditionVariableDeclStmt()));
    }

    // Handle the case where the dynamic expression is in the condition of the
    // stmt.
    ASTNodeInfo IfCondInfo = Visit(Node->getCond());
    if (IfCondInfo.isForReplacement())
      if (Expr* IfCondExpr = IfCondInfo.getAs<Expr>()) {
          Node->setCond(SubstituteUnknownSymbol(m_Context->BoolTy, IfCondExpr));
          return ASTNodeInfo(Node, /*needs eval*/false);
      }

    // Visit the other parts - they will fall naturally into Stmt or
    // CompoundStmt where we know what to do.
    Visit(Node->getThen());
    if (Stmt* ElseExpr = Node->getElse())
      Visit(ElseExpr);

    return ASTNodeInfo(Node, false);
  }
示例#2
0
  ASTNodeInfo EvaluateTSynthesizer::VisitBinaryOperator(BinaryOperator* Node) {    
    ASTNodeInfo rhs = Visit(Node->getRHS());
    ASTNodeInfo lhs;

    lhs = Visit(Node->getLHS());

    assert((lhs.hasSingleNode() || rhs.hasSingleNode()) &&
           "1:N replacements are not implemented yet!");

    // Try find out the type of the left-hand-side of the operator
    // and give the hint to the right-hand-side in order to replace the
    // dependent symbol
    if (Node->isAssignmentOp() && rhs.isForReplacement() &&
        !lhs.isForReplacement()) {
      if (Expr* LHSExpr = lhs.getAs<Expr>())
        if (!IsArtificiallyDependent(LHSExpr)) {
          const QualType LHSTy = LHSExpr->getType();
          Node->setRHS(SubstituteUnknownSymbol(LHSTy, rhs.castTo<Expr>()));
          Node->setTypeDependent(false);
          Node->setValueDependent(false);
          return ASTNodeInfo(Node, /*needs eval*/false);
        }
    }

    return ASTNodeInfo(Node, IsArtificiallyDependent(Node));
  }
示例#3
0
  ASTNodeInfo EvaluateTSynthesizer::VisitCompoundStmt(CompoundStmt* Node) {
    ++m_NestedCompoundStmts;
    ASTNodes Children;
    ASTNodes NewChildren;
    if (GetChildren(Children, Node)) {
      ASTNodes::iterator it;
      for (it = Children.begin(); it != Children.end(); ++it) {
        ASTNodeInfo NewNode = Visit(*it);
        if (!NewNode.hasSingleNode()) {

          ASTNodes& NewStmts(NewNode.getNodes());
          for(unsigned i = 0; i < NewStmts.size(); ++i)
            NewChildren.push_back(NewStmts[i]);

          Node->setStmts(*m_Context, NewChildren.data(), NewChildren.size());
          // Resolve all 1:n replacements
          Visit(Node);
        }
        else {
          if (NewNode.isForReplacement()) {
            if (Expr* E = NewNode.getAs<Expr>()) {
              // Check whether value printer has been requested
              bool valuePrinterReq = false;
              // If this was the last or the last is not null stmt, means that 
              // we need to value print.
              // If this is in a wrapper function's body then look for VP.
              if (FunctionDecl* FD = dyn_cast<FunctionDecl>(m_CurDeclContext))
                valuePrinterReq 
                  = m_NestedCompoundStmts < 2  && utils::Analyze::IsWrapper(FD) 
                  && ((it+1) == Children.end() || ((it+2) == Children.end() 
                                                   && !isa<NullStmt>(*(it+1))));

              // Assume void if still not escaped
              NewChildren.push_back(SubstituteUnknownSymbol(m_Context->VoidTy,E,
                                                            valuePrinterReq));
            }
          }
          else
            NewChildren.push_back(*it);
        }
      }
    }

    Node->setStmts(*m_Context, NewChildren.data(), NewChildren.size());

    --m_NestedCompoundStmts;
    return ASTNodeInfo(Node, 0);
  }
示例#4
0
 ASTNodeInfo EvaluateTSynthesizer::VisitExpr(Expr* Node) {
   for (Stmt::child_iterator
          I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
     if (*I) {
       ASTNodeInfo NewNode = Visit(*I);
       assert(NewNode.hasSingleNode() &&
              "Cannot have more than one stmt at that point");
       if (NewNode.isForReplacement()) {
         if (Expr *E = NewNode.getAs<Expr>())
           // Assume void if still not escaped
           *I = SubstituteUnknownSymbol(m_Context->VoidTy, E);
       }
       else {
         *I = NewNode.getAsSingleNode();
       }
     }
   }
   return ASTNodeInfo(Node, 0);
 }
  ASTNodeInfo EvaluateTSynthesizer::VisitCompoundStmt(CompoundStmt* Node) {
    ASTNodes Children;
    ASTNodes NewChildren;
    if (GetChildren(Children, Node)) {
      ASTNodes::iterator it;
      for (it = Children.begin(); it != Children.end(); ++it) {
        ASTNodeInfo NewNode = Visit(*it);
        if (!NewNode.hasSingleNode()) {

          ASTNodes& NewStmts(NewNode.getNodes());
          for(unsigned i = 0; i < NewStmts.size(); ++i)
            NewChildren.push_back(NewStmts[i]);

          Node->setStmts(*m_Context, NewChildren.data(), NewChildren.size());
          // Resolve all 1:n replacements
          Visit(Node);
        }
        else {
          if (NewNode.isForReplacement()) {
            if (Expr* E = NewNode.getAs<Expr>()) {
              // Check whether value printer has been requested
              bool valuePrinterReq = false;
              if ((it+1) == Children.end() || !isa<NullStmt>(*(it+1)))
                valuePrinterReq = true;

              // Assume void if still not escaped
              NewChildren.push_back(SubstituteUnknownSymbol(m_Context->VoidTy,E,
                                                            valuePrinterReq));
            }
          }
          else
            NewChildren.push_back(*it);
        }
      }
    }

    Node->setStmts(*m_Context, NewChildren.data(), NewChildren.size());

    return ASTNodeInfo(Node, 0);

  }
示例#6
0
 ASTNodeInfo EvaluateTSynthesizer::VisitDependentScopeDeclRefExpr(
                                             DependentScopeDeclRefExpr* Node) {
   return ASTNodeInfo(Node, IsArtificiallyDependent(Node));
 }
示例#7
0
 ASTNodeInfo EvaluateTSynthesizer::VisitDeclRefExpr(DeclRefExpr* DRE) {
   return ASTNodeInfo(DRE, IsArtificiallyDependent(DRE));
 }
示例#8
0
 ASTNodeInfo EvaluateTSynthesizer::VisitCallExpr(CallExpr* E) {
   // FIXME: Maybe we need to handle the arguments
   // ASTNodeInfo NewNode = Visit(E->getCallee());
   return ASTNodeInfo (E, IsArtificiallyDependent(E));
 }
示例#9
0
 ASTNodeInfo EvaluateTSynthesizer::VisitCXXDeleteExpr(CXXDeleteExpr* Node) {
   ASTNodeInfo deleteArg = Visit(Node->getArgument());
   return ASTNodeInfo(Node, /*needs eval*/deleteArg.isForReplacement());
 }
示例#10
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);
  }