void
    TraverseTUnitConsumer::InvestigateASTContextTypes( ASTContext& context )
    {
      // const SmallVectorImpl<Type *>&
      auto& types = context.getTypes();

      TypePrinter printer(context.getPrintingPolicy(), /* indentation */ 2);

      const char *placeholder = ""; // "hey"

      for(const Type *type : types) {
        llvm::errs() << " - ";
        printer.print(type, Qualifiers(), llvm::errs(), placeholder);
        llvm::errs() << "\n";
      }

      (terrs().magenta() << "InvestigateASTContextTypes(): END.\n").reset();
    }
static Qualifiers getDeclQualifiers(const Decl *D) {
  if(auto Value = dyn_cast<ValueDecl>(D))
    return Value->getType().split().second;
  return Qualifiers();
}
  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;
  }