15ffd83dbSDimitry Andric //===-- ASTResultSynthesizer.cpp ------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "ASTResultSynthesizer.h"
100b57cec5SDimitry Andric
115ffd83dbSDimitry Andric #include "ClangASTImporter.h"
120b57cec5SDimitry Andric #include "ClangPersistentVariables.h"
130b57cec5SDimitry Andric
145ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
150b57cec5SDimitry Andric #include "lldb/Target/Target.h"
160b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
1781ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
180b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
190b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
200b57cec5SDimitry Andric #include "clang/AST/Decl.h"
210b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
220b57cec5SDimitry Andric #include "clang/AST/DeclGroup.h"
230b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
240b57cec5SDimitry Andric #include "clang/AST/Expr.h"
250b57cec5SDimitry Andric #include "clang/AST/Stmt.h"
260b57cec5SDimitry Andric #include "clang/Parse/Parser.h"
270b57cec5SDimitry Andric #include "clang/Sema/SemaDiagnostic.h"
280b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
30fe6060f1SDimitry Andric #include <cstdlib>
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric using namespace llvm;
330b57cec5SDimitry Andric using namespace clang;
340b57cec5SDimitry Andric using namespace lldb_private;
350b57cec5SDimitry Andric
ASTResultSynthesizer(ASTConsumer * passthrough,bool top_level,Target & target)360b57cec5SDimitry Andric ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
370b57cec5SDimitry Andric bool top_level, Target &target)
380b57cec5SDimitry Andric : m_ast_context(nullptr), m_passthrough(passthrough),
390b57cec5SDimitry Andric m_passthrough_sema(nullptr), m_target(target), m_sema(nullptr),
400b57cec5SDimitry Andric m_top_level(top_level) {
410b57cec5SDimitry Andric if (!m_passthrough)
420b57cec5SDimitry Andric return;
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric
47fe6060f1SDimitry Andric ASTResultSynthesizer::~ASTResultSynthesizer() = default;
480b57cec5SDimitry Andric
Initialize(ASTContext & Context)490b57cec5SDimitry Andric void ASTResultSynthesizer::Initialize(ASTContext &Context) {
500b57cec5SDimitry Andric m_ast_context = &Context;
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric if (m_passthrough)
530b57cec5SDimitry Andric m_passthrough->Initialize(Context);
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric
TransformTopLevelDecl(Decl * D)560b57cec5SDimitry Andric void ASTResultSynthesizer::TransformTopLevelDecl(Decl *D) {
5781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Expressions);
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D)) {
600b57cec5SDimitry Andric if (log && log->GetVerbose()) {
610b57cec5SDimitry Andric if (named_decl->getIdentifier())
629dba64beSDimitry Andric LLDB_LOGF(log, "TransformTopLevelDecl(%s)",
630b57cec5SDimitry Andric named_decl->getIdentifier()->getNameStart());
640b57cec5SDimitry Andric else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
659dba64beSDimitry Andric LLDB_LOGF(log, "TransformTopLevelDecl(%s)",
660b57cec5SDimitry Andric method_decl->getSelector().getAsString().c_str());
670b57cec5SDimitry Andric else
689dba64beSDimitry Andric LLDB_LOGF(log, "TransformTopLevelDecl(<complex>)");
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric if (m_top_level) {
720b57cec5SDimitry Andric RecordPersistentDecl(named_decl);
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D)) {
770b57cec5SDimitry Andric RecordDecl::decl_iterator decl_iterator;
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric for (decl_iterator = linkage_spec_decl->decls_begin();
800b57cec5SDimitry Andric decl_iterator != linkage_spec_decl->decls_end(); ++decl_iterator) {
810b57cec5SDimitry Andric TransformTopLevelDecl(*decl_iterator);
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric } else if (!m_top_level) {
840b57cec5SDimitry Andric if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D)) {
850b57cec5SDimitry Andric if (m_ast_context &&
860b57cec5SDimitry Andric !method_decl->getSelector().getAsString().compare("$__lldb_expr:")) {
870b57cec5SDimitry Andric RecordPersistentTypes(method_decl);
880b57cec5SDimitry Andric SynthesizeObjCMethodResult(method_decl);
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric } else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D)) {
910b57cec5SDimitry Andric // When completing user input the body of the function may be a nullptr.
920b57cec5SDimitry Andric if (m_ast_context && function_decl->hasBody() &&
930b57cec5SDimitry Andric !function_decl->getNameInfo().getAsString().compare("$__lldb_expr")) {
940b57cec5SDimitry Andric RecordPersistentTypes(function_decl);
950b57cec5SDimitry Andric SynthesizeFunctionResult(function_decl);
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric
HandleTopLevelDecl(DeclGroupRef D)1010b57cec5SDimitry Andric bool ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D) {
1020b57cec5SDimitry Andric DeclGroupRef::iterator decl_iterator;
1030b57cec5SDimitry Andric
1040b57cec5SDimitry Andric for (decl_iterator = D.begin(); decl_iterator != D.end(); ++decl_iterator) {
1050b57cec5SDimitry Andric Decl *decl = *decl_iterator;
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric TransformTopLevelDecl(decl);
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric if (m_passthrough)
1110b57cec5SDimitry Andric return m_passthrough->HandleTopLevelDecl(D);
1120b57cec5SDimitry Andric return true;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
SynthesizeFunctionResult(FunctionDecl * FunDecl)1150b57cec5SDimitry Andric bool ASTResultSynthesizer::SynthesizeFunctionResult(FunctionDecl *FunDecl) {
11681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Expressions);
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric if (!m_sema)
1190b57cec5SDimitry Andric return false;
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric FunctionDecl *function_decl = FunDecl;
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric if (!function_decl)
1240b57cec5SDimitry Andric return false;
1250b57cec5SDimitry Andric
1260b57cec5SDimitry Andric if (log && log->GetVerbose()) {
1270b57cec5SDimitry Andric std::string s;
1280b57cec5SDimitry Andric raw_string_ostream os(s);
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric function_decl->print(os);
1310b57cec5SDimitry Andric
1320b57cec5SDimitry Andric os.flush();
1330b57cec5SDimitry Andric
1349dba64beSDimitry Andric LLDB_LOGF(log, "Untransformed function AST:\n%s", s.c_str());
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric
1370b57cec5SDimitry Andric Stmt *function_body = function_decl->getBody();
1380b57cec5SDimitry Andric CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric bool ret = SynthesizeBodyResult(compound_stmt, function_decl);
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric if (log && log->GetVerbose()) {
1430b57cec5SDimitry Andric std::string s;
1440b57cec5SDimitry Andric raw_string_ostream os(s);
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andric function_decl->print(os);
1470b57cec5SDimitry Andric
1480b57cec5SDimitry Andric os.flush();
1490b57cec5SDimitry Andric
1509dba64beSDimitry Andric LLDB_LOGF(log, "Transformed function AST:\n%s", s.c_str());
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric
1530b57cec5SDimitry Andric return ret;
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric
SynthesizeObjCMethodResult(ObjCMethodDecl * MethodDecl)1560b57cec5SDimitry Andric bool ASTResultSynthesizer::SynthesizeObjCMethodResult(
1570b57cec5SDimitry Andric ObjCMethodDecl *MethodDecl) {
15881ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Expressions);
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric if (!m_sema)
1610b57cec5SDimitry Andric return false;
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric if (!MethodDecl)
1640b57cec5SDimitry Andric return false;
1650b57cec5SDimitry Andric
1660b57cec5SDimitry Andric if (log && log->GetVerbose()) {
1670b57cec5SDimitry Andric std::string s;
1680b57cec5SDimitry Andric raw_string_ostream os(s);
1690b57cec5SDimitry Andric
1700b57cec5SDimitry Andric MethodDecl->print(os);
1710b57cec5SDimitry Andric
1720b57cec5SDimitry Andric os.flush();
1730b57cec5SDimitry Andric
1749dba64beSDimitry Andric LLDB_LOGF(log, "Untransformed method AST:\n%s", s.c_str());
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric
1770b57cec5SDimitry Andric Stmt *method_body = MethodDecl->getBody();
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric if (!method_body)
1800b57cec5SDimitry Andric return false;
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body);
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric bool ret = SynthesizeBodyResult(compound_stmt, MethodDecl);
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric if (log && log->GetVerbose()) {
1870b57cec5SDimitry Andric std::string s;
1880b57cec5SDimitry Andric raw_string_ostream os(s);
1890b57cec5SDimitry Andric
1900b57cec5SDimitry Andric MethodDecl->print(os);
1910b57cec5SDimitry Andric
1920b57cec5SDimitry Andric os.flush();
1930b57cec5SDimitry Andric
1949dba64beSDimitry Andric LLDB_LOGF(log, "Transformed method AST:\n%s", s.c_str());
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric
1970b57cec5SDimitry Andric return ret;
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric
200fcaf7f86SDimitry Andric /// Returns true if LLDB can take the address of the given lvalue for the sake
201fcaf7f86SDimitry Andric /// of capturing the expression result. Returns false if LLDB should instead
202fcaf7f86SDimitry Andric /// store the expression result in a result variable.
CanTakeAddressOfLValue(const Expr * lvalue_expr)203fcaf7f86SDimitry Andric static bool CanTakeAddressOfLValue(const Expr *lvalue_expr) {
204fcaf7f86SDimitry Andric assert(lvalue_expr->getValueKind() == VK_LValue &&
205fcaf7f86SDimitry Andric "lvalue_expr not a lvalue");
206fcaf7f86SDimitry Andric
207fcaf7f86SDimitry Andric QualType qt = lvalue_expr->getType();
208fcaf7f86SDimitry Andric // If the lvalue has const-qualified non-volatile integral or enum type, then
209fcaf7f86SDimitry Andric // the underlying value might come from a const static data member as
210fcaf7f86SDimitry Andric // described in C++11 [class.static.data]p3. If that's the case, then the
211fcaf7f86SDimitry Andric // value might not have an address if the user didn't also define the member
212fcaf7f86SDimitry Andric // in a namespace scope. Taking the address would cause that LLDB later fails
213fcaf7f86SDimitry Andric // to link the expression, so those lvalues should be stored in a result
214fcaf7f86SDimitry Andric // variable.
215fcaf7f86SDimitry Andric if (qt->isIntegralOrEnumerationType() && qt.isConstQualified() &&
216fcaf7f86SDimitry Andric !qt.isVolatileQualified())
217fcaf7f86SDimitry Andric return false;
218fcaf7f86SDimitry Andric return true;
219fcaf7f86SDimitry Andric }
220fcaf7f86SDimitry Andric
SynthesizeBodyResult(CompoundStmt * Body,DeclContext * DC)2210b57cec5SDimitry Andric bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body,
2220b57cec5SDimitry Andric DeclContext *DC) {
22381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Expressions);
2240b57cec5SDimitry Andric
2250b57cec5SDimitry Andric ASTContext &Ctx(*m_ast_context);
2260b57cec5SDimitry Andric
2270b57cec5SDimitry Andric if (!Body)
2280b57cec5SDimitry Andric return false;
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andric if (Body->body_empty())
2310b57cec5SDimitry Andric return false;
2320b57cec5SDimitry Andric
2330b57cec5SDimitry Andric Stmt **last_stmt_ptr = Body->body_end() - 1;
2340b57cec5SDimitry Andric Stmt *last_stmt = *last_stmt_ptr;
2350b57cec5SDimitry Andric
2360eae32dcSDimitry Andric while (isa<NullStmt>(last_stmt)) {
2370b57cec5SDimitry Andric if (last_stmt_ptr != Body->body_begin()) {
2380b57cec5SDimitry Andric last_stmt_ptr--;
2390b57cec5SDimitry Andric last_stmt = *last_stmt_ptr;
2400b57cec5SDimitry Andric } else {
2410b57cec5SDimitry Andric return false;
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric Expr *last_expr = dyn_cast<Expr>(last_stmt);
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric if (!last_expr)
2480b57cec5SDimitry Andric // No auxiliary variable necessary; expression returns void
2490b57cec5SDimitry Andric return true;
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric // In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off
2520b57cec5SDimitry Andric // if that's the case.
2530b57cec5SDimitry Andric
2540b57cec5SDimitry Andric do {
2550b57cec5SDimitry Andric ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andric if (!implicit_cast)
2580b57cec5SDimitry Andric break;
2590b57cec5SDimitry Andric
2600b57cec5SDimitry Andric if (implicit_cast->getCastKind() != CK_LValueToRValue)
2610b57cec5SDimitry Andric break;
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric last_expr = implicit_cast->getSubExpr();
2640b57cec5SDimitry Andric } while (false);
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric // is_lvalue is used to record whether the expression returns an assignable
2670b57cec5SDimitry Andric // Lvalue or an Rvalue. This is relevant because they are handled
2680b57cec5SDimitry Andric // differently.
2690b57cec5SDimitry Andric //
2700b57cec5SDimitry Andric // For Lvalues
2710b57cec5SDimitry Andric //
2720b57cec5SDimitry Andric // - In AST result synthesis (here!) the expression E is transformed into an
2735ffd83dbSDimitry Andric // initialization T *$__lldb_expr_result_ptr = &E.
2740b57cec5SDimitry Andric //
2750b57cec5SDimitry Andric // - In structure allocation, a pointer-sized slot is allocated in the
2765ffd83dbSDimitry Andric // struct that is to be passed into the expression.
2770b57cec5SDimitry Andric //
2780b57cec5SDimitry Andric // - In IR transformations, reads and writes to $__lldb_expr_result_ptr are
2795ffd83dbSDimitry Andric // redirected at an entry in the struct ($__lldb_arg) passed into the
2805ffd83dbSDimitry Andric // expression. (Other persistent variables are treated similarly, having
2815ffd83dbSDimitry Andric // been materialized as references, but in those cases the value of the
2825ffd83dbSDimitry Andric // reference itself is never modified.)
2830b57cec5SDimitry Andric //
2840b57cec5SDimitry Andric // - During materialization, $0 (the result persistent variable) is ignored.
2850b57cec5SDimitry Andric //
2860b57cec5SDimitry Andric // - During dematerialization, $0 is marked up as a load address with value
2875ffd83dbSDimitry Andric // equal to the contents of the structure entry.
2880b57cec5SDimitry Andric //
289fcaf7f86SDimitry Andric // - Note: if we cannot take an address of the resulting Lvalue (e.g. it's
290fcaf7f86SDimitry Andric // a static const member without an out-of-class definition), then we
291fcaf7f86SDimitry Andric // follow the Rvalue route.
292fcaf7f86SDimitry Andric //
2930b57cec5SDimitry Andric // For Rvalues
2940b57cec5SDimitry Andric //
2950b57cec5SDimitry Andric // - In AST result synthesis the expression E is transformed into an
2965ffd83dbSDimitry Andric // initialization static T $__lldb_expr_result = E.
2970b57cec5SDimitry Andric //
2980b57cec5SDimitry Andric // - In structure allocation, a pointer-sized slot is allocated in the
2995ffd83dbSDimitry Andric // struct that is to be passed into the expression.
3000b57cec5SDimitry Andric //
3010b57cec5SDimitry Andric // - In IR transformations, an instruction is inserted at the beginning of
3025ffd83dbSDimitry Andric // the function to dereference the pointer resident in the slot. Reads and
3035ffd83dbSDimitry Andric // writes to $__lldb_expr_result are redirected at that dereferenced
3045ffd83dbSDimitry Andric // version. Guard variables for the static variable are excised.
3050b57cec5SDimitry Andric //
3060b57cec5SDimitry Andric // - During materialization, $0 (the result persistent variable) is
3075ffd83dbSDimitry Andric // populated with the location of a newly-allocated area of memory.
3080b57cec5SDimitry Andric //
3090b57cec5SDimitry Andric // - During dematerialization, $0 is ignored.
3100b57cec5SDimitry Andric
3110b57cec5SDimitry Andric bool is_lvalue = last_expr->getValueKind() == VK_LValue &&
3120b57cec5SDimitry Andric last_expr->getObjectKind() == OK_Ordinary;
3130b57cec5SDimitry Andric
3140b57cec5SDimitry Andric QualType expr_qual_type = last_expr->getType();
3150b57cec5SDimitry Andric const clang::Type *expr_type = expr_qual_type.getTypePtr();
3160b57cec5SDimitry Andric
3170b57cec5SDimitry Andric if (!expr_type)
3180b57cec5SDimitry Andric return false;
3190b57cec5SDimitry Andric
3200b57cec5SDimitry Andric if (expr_type->isVoidType())
3210b57cec5SDimitry Andric return true;
3220b57cec5SDimitry Andric
3230b57cec5SDimitry Andric if (log) {
3240b57cec5SDimitry Andric std::string s = expr_qual_type.getAsString();
3250b57cec5SDimitry Andric
3269dba64beSDimitry Andric LLDB_LOGF(log, "Last statement is an %s with type: %s",
3270b57cec5SDimitry Andric (is_lvalue ? "lvalue" : "rvalue"), s.c_str());
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andric clang::VarDecl *result_decl = nullptr;
3310b57cec5SDimitry Andric
332fcaf7f86SDimitry Andric if (is_lvalue && CanTakeAddressOfLValue(last_expr)) {
3330b57cec5SDimitry Andric IdentifierInfo *result_ptr_id;
3340b57cec5SDimitry Andric
3350b57cec5SDimitry Andric if (expr_type->isFunctionType())
3360b57cec5SDimitry Andric result_ptr_id =
3370b57cec5SDimitry Andric &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should
3380b57cec5SDimitry Andric // be treated like function
3390b57cec5SDimitry Andric // pointers
3400b57cec5SDimitry Andric else
3410b57cec5SDimitry Andric result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr");
3420b57cec5SDimitry Andric
3435ffd83dbSDimitry Andric m_sema->RequireCompleteType(last_expr->getSourceRange().getBegin(),
3445ffd83dbSDimitry Andric expr_qual_type,
3450b57cec5SDimitry Andric clang::diag::err_incomplete_type);
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andric QualType ptr_qual_type;
3480b57cec5SDimitry Andric
3490b57cec5SDimitry Andric if (expr_qual_type->getAs<ObjCObjectType>() != nullptr)
3500b57cec5SDimitry Andric ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type);
3510b57cec5SDimitry Andric else
3520b57cec5SDimitry Andric ptr_qual_type = Ctx.getPointerType(expr_qual_type);
3530b57cec5SDimitry Andric
3540b57cec5SDimitry Andric result_decl =
3550b57cec5SDimitry Andric VarDecl::Create(Ctx, DC, SourceLocation(), SourceLocation(),
3560b57cec5SDimitry Andric result_ptr_id, ptr_qual_type, nullptr, SC_Static);
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andric if (!result_decl)
3590b57cec5SDimitry Andric return false;
3600b57cec5SDimitry Andric
3610b57cec5SDimitry Andric ExprResult address_of_expr =
3620b57cec5SDimitry Andric m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr);
3630b57cec5SDimitry Andric if (address_of_expr.get())
3640b57cec5SDimitry Andric m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(), true);
3650b57cec5SDimitry Andric else
3660b57cec5SDimitry Andric return false;
3670b57cec5SDimitry Andric } else {
3680b57cec5SDimitry Andric IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
3690b57cec5SDimitry Andric
3700b57cec5SDimitry Andric result_decl =
3710b57cec5SDimitry Andric VarDecl::Create(Ctx, DC, SourceLocation(), SourceLocation(), &result_id,
3720b57cec5SDimitry Andric expr_qual_type, nullptr, SC_Static);
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andric if (!result_decl)
3750b57cec5SDimitry Andric return false;
3760b57cec5SDimitry Andric
3770b57cec5SDimitry Andric m_sema->AddInitializerToDecl(result_decl, last_expr, true);
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric
3800b57cec5SDimitry Andric DC->addDecl(result_decl);
3810b57cec5SDimitry Andric
3820b57cec5SDimitry Andric ///////////////////////////////
3830b57cec5SDimitry Andric // call AddInitializerToDecl
3840b57cec5SDimitry Andric //
3850b57cec5SDimitry Andric
3860b57cec5SDimitry Andric // m_sema->AddInitializerToDecl(result_decl, last_expr);
3870b57cec5SDimitry Andric
3880b57cec5SDimitry Andric /////////////////////////////////
3890b57cec5SDimitry Andric // call ConvertDeclToDeclGroup
3900b57cec5SDimitry Andric //
3910b57cec5SDimitry Andric
3920b57cec5SDimitry Andric Sema::DeclGroupPtrTy result_decl_group_ptr;
3930b57cec5SDimitry Andric
3940b57cec5SDimitry Andric result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl);
3950b57cec5SDimitry Andric
3960b57cec5SDimitry Andric ////////////////////////
3970b57cec5SDimitry Andric // call ActOnDeclStmt
3980b57cec5SDimitry Andric //
3990b57cec5SDimitry Andric
4000b57cec5SDimitry Andric StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(
4010b57cec5SDimitry Andric result_decl_group_ptr, SourceLocation(), SourceLocation()));
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric ////////////////////////////////////////////////
4040b57cec5SDimitry Andric // replace the old statement with the new one
4050b57cec5SDimitry Andric //
4060b57cec5SDimitry Andric
407480093f4SDimitry Andric *last_stmt_ptr = static_cast<Stmt *>(result_initialization_stmt_result.get());
4080b57cec5SDimitry Andric
4090b57cec5SDimitry Andric return true;
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric
HandleTranslationUnit(ASTContext & Ctx)4120b57cec5SDimitry Andric void ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx) {
4130b57cec5SDimitry Andric if (m_passthrough)
4140b57cec5SDimitry Andric m_passthrough->HandleTranslationUnit(Ctx);
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric
RecordPersistentTypes(DeclContext * FunDeclCtx)4170b57cec5SDimitry Andric void ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx) {
4180b57cec5SDimitry Andric typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator;
4190b57cec5SDimitry Andric
4200b57cec5SDimitry Andric for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()),
4210b57cec5SDimitry Andric e = TypeDeclIterator(FunDeclCtx->decls_end());
4220b57cec5SDimitry Andric i != e; ++i) {
4230b57cec5SDimitry Andric MaybeRecordPersistentType(*i);
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric
MaybeRecordPersistentType(TypeDecl * D)4270b57cec5SDimitry Andric void ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D) {
4280b57cec5SDimitry Andric if (!D->getIdentifier())
4290b57cec5SDimitry Andric return;
4300b57cec5SDimitry Andric
4310b57cec5SDimitry Andric StringRef name = D->getName();
432*06c3fb27SDimitry Andric if (name.empty() || name.front() != '$')
4330b57cec5SDimitry Andric return;
4340b57cec5SDimitry Andric
435*06c3fb27SDimitry Andric LLDB_LOG(GetLog(LLDBLog::Expressions), "Recording persistent type {0}", name);
4360b57cec5SDimitry Andric
4370b57cec5SDimitry Andric m_decls.push_back(D);
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric
RecordPersistentDecl(NamedDecl * D)4400b57cec5SDimitry Andric void ASTResultSynthesizer::RecordPersistentDecl(NamedDecl *D) {
4410b57cec5SDimitry Andric lldbassert(m_top_level);
4420b57cec5SDimitry Andric
4430b57cec5SDimitry Andric if (!D->getIdentifier())
4440b57cec5SDimitry Andric return;
4450b57cec5SDimitry Andric
4460b57cec5SDimitry Andric StringRef name = D->getName();
447*06c3fb27SDimitry Andric if (name.empty())
4480b57cec5SDimitry Andric return;
4490b57cec5SDimitry Andric
450*06c3fb27SDimitry Andric LLDB_LOG(GetLog(LLDBLog::Expressions), "Recording persistent decl {0}", name);
4510b57cec5SDimitry Andric
4520b57cec5SDimitry Andric m_decls.push_back(D);
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric
CommitPersistentDecls()4550b57cec5SDimitry Andric void ASTResultSynthesizer::CommitPersistentDecls() {
456480093f4SDimitry Andric auto *state =
457480093f4SDimitry Andric m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC);
458480093f4SDimitry Andric if (!state)
459480093f4SDimitry Andric return;
460480093f4SDimitry Andric
461480093f4SDimitry Andric auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
462e8d8bef9SDimitry Andric
463bdd1243dSDimitry Andric lldb::TypeSystemClangSP scratch_ts_sp = ScratchTypeSystemClang::GetForTarget(
464e8d8bef9SDimitry Andric m_target, m_ast_context->getLangOpts());
465480093f4SDimitry Andric
4660b57cec5SDimitry Andric for (clang::NamedDecl *decl : m_decls) {
4670b57cec5SDimitry Andric StringRef name = decl->getName();
4680b57cec5SDimitry Andric
4695ffd83dbSDimitry Andric Decl *D_scratch = persistent_vars->GetClangASTImporter()->DeportDecl(
470bdd1243dSDimitry Andric &scratch_ts_sp->getASTContext(), decl);
4710b57cec5SDimitry Andric
4720b57cec5SDimitry Andric if (!D_scratch) {
47381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Expressions);
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric if (log) {
4760b57cec5SDimitry Andric std::string s;
4770b57cec5SDimitry Andric llvm::raw_string_ostream ss(s);
4780b57cec5SDimitry Andric decl->dump(ss);
4790b57cec5SDimitry Andric ss.flush();
4800b57cec5SDimitry Andric
4819dba64beSDimitry Andric LLDB_LOGF(log, "Couldn't commit persistent decl: %s\n", s.c_str());
4820b57cec5SDimitry Andric }
4830b57cec5SDimitry Andric
4840b57cec5SDimitry Andric continue;
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric
4870b57cec5SDimitry Andric if (NamedDecl *NamedDecl_scratch = dyn_cast<NamedDecl>(D_scratch))
488*06c3fb27SDimitry Andric persistent_vars->RegisterPersistentDecl(ConstString(name),
489*06c3fb27SDimitry Andric NamedDecl_scratch, scratch_ts_sp);
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric }
4920b57cec5SDimitry Andric
HandleTagDeclDefinition(TagDecl * D)4930b57cec5SDimitry Andric void ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D) {
4940b57cec5SDimitry Andric if (m_passthrough)
4950b57cec5SDimitry Andric m_passthrough->HandleTagDeclDefinition(D);
4960b57cec5SDimitry Andric }
4970b57cec5SDimitry Andric
CompleteTentativeDefinition(VarDecl * D)4980b57cec5SDimitry Andric void ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D) {
4990b57cec5SDimitry Andric if (m_passthrough)
5000b57cec5SDimitry Andric m_passthrough->CompleteTentativeDefinition(D);
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric
HandleVTable(CXXRecordDecl * RD)5030b57cec5SDimitry Andric void ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD) {
5040b57cec5SDimitry Andric if (m_passthrough)
5050b57cec5SDimitry Andric m_passthrough->HandleVTable(RD);
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric
PrintStats()5080b57cec5SDimitry Andric void ASTResultSynthesizer::PrintStats() {
5090b57cec5SDimitry Andric if (m_passthrough)
5100b57cec5SDimitry Andric m_passthrough->PrintStats();
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric
InitializeSema(Sema & S)5130b57cec5SDimitry Andric void ASTResultSynthesizer::InitializeSema(Sema &S) {
5140b57cec5SDimitry Andric m_sema = &S;
5150b57cec5SDimitry Andric
5160b57cec5SDimitry Andric if (m_passthrough_sema)
5170b57cec5SDimitry Andric m_passthrough_sema->InitializeSema(S);
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric
ForgetSema()5200b57cec5SDimitry Andric void ASTResultSynthesizer::ForgetSema() {
5210b57cec5SDimitry Andric m_sema = nullptr;
5220b57cec5SDimitry Andric
5230b57cec5SDimitry Andric if (m_passthrough_sema)
5240b57cec5SDimitry Andric m_passthrough_sema->ForgetSema();
5250b57cec5SDimitry Andric }
526