Expr* EvaluateTSynthesizer::SubstituteUnknownSymbol(const QualType InstTy, Expr* SubTree, bool ValuePrinterReq) { assert(SubTree && "No subtree specified!"); //Build the arguments for the call llvm::SmallVector<Expr*, 2> CallArgs; // Build Arg0 Expr* Arg0 = BuildDynamicExprInfo(SubTree, ValuePrinterReq); CallArgs.push_back(Arg0); // Build Arg1 QualType DCTy = m_Context->getTypeDeclType(m_DeclContextDecl); Expr* Arg1 = utils::Synthesize::CStyleCastPtrExpr(m_Sema, DCTy, (uint64_t)m_CurDeclContext); CallArgs.push_back(Arg1); // Build the call assert(Arg0 && Arg1 && "Arguments missing!"); CallExpr* EvalCall = BuildEvalCallExpr(InstTy, SubTree, CallArgs); // Add substitution mapping getSubstSymbolMap()[EvalCall] = SubTree; return EvalCall; }
Expr* EvaluateTSynthesizer::SubstituteUnknownSymbol(const QualType InstTy, Expr* SubTree, bool ValuePrinterReq) { assert(SubTree && "No subtree specified!"); //Build the arguments for the call ASTOwningVector<Expr*> CallArgs(*m_Sema); // Build Arg0 Expr* Arg0 = BuildDynamicExprInfo(SubTree, ValuePrinterReq); CallArgs.push_back(Arg0); // Build Arg1 CXXRecordDecl* D = dyn_cast<CXXRecordDecl>(m_Interpreter-> LookupDecl("clang"). LookupDecl("DeclContext"). getSingleDecl()); assert(D && "DeclContext declaration not found!"); QualType DCTy = m_Context->getTypeDeclType(D); Expr* Arg1 = ConstructCStyleCasePtrExpr(DCTy, (uint64_t)m_CurDeclContext); CallArgs.push_back(Arg1); // Build the call assert(Arg0 && Arg1 && "Arguments missing!"); CallExpr* EvalCall = BuildEvalCallExpr(InstTy, SubTree, CallArgs); // Add substitution mapping getSubstSymbolMap()[EvalCall] = SubTree; return EvalCall; }
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); }