const NamedDecl &findDecl(ParsedAST &AST, llvm::StringRef QName) { llvm::SmallVector<llvm::StringRef, 4> Components; QName.split(Components, "::"); auto &Ctx = AST.getASTContext(); auto LookupDecl = [&Ctx](const DeclContext &Scope, llvm::StringRef Name) -> const NamedDecl & { auto LookupRes = Scope.lookup(DeclarationName(&Ctx.Idents.get(Name))); assert(!LookupRes.empty() && "Lookup failed"); assert(LookupRes.size() == 1 && "Lookup returned multiple results"); return *LookupRes.front(); }; const DeclContext *Scope = Ctx.getTranslationUnitDecl(); for (auto NameIt = Components.begin(), End = Components.end() - 1; NameIt != End; ++NameIt) { Scope = &cast<DeclContext>(LookupDecl(*Scope, *NameIt)); } return LookupDecl(*Scope, Components.back()); }
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; }