diff options
Diffstat (limited to 'lldb/source/Plugins/ExpressionParser/Clang')
28 files changed, 10394 insertions, 11142 deletions
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp index 0b819948115..3c20b516c10 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp @@ -18,118 +18,94 @@ using namespace lldb_private; -ASTDumper::ASTDumper (clang::Decl *decl) -{ - clang::DeclContext *decl_ctx = llvm::dyn_cast<clang::DeclContext>(decl); - - bool has_external_lexical_storage; - bool has_external_visible_storage; - - if (decl_ctx) - { - has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); - has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); - decl_ctx->setHasExternalLexicalStorage(false); - decl_ctx->setHasExternalVisibleStorage(false); - } - - llvm::raw_string_ostream os(m_dump); - decl->print (os); - os.flush(); - - if (decl_ctx) - { - decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); - decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); - } -} +ASTDumper::ASTDumper(clang::Decl *decl) { + clang::DeclContext *decl_ctx = llvm::dyn_cast<clang::DeclContext>(decl); + + bool has_external_lexical_storage; + bool has_external_visible_storage; -ASTDumper::ASTDumper (clang::DeclContext *decl_ctx) -{ - bool has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); - bool has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); - + if (decl_ctx) { + has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); + has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); decl_ctx->setHasExternalLexicalStorage(false); decl_ctx->setHasExternalVisibleStorage(false); - - if (clang::Decl *decl = llvm::dyn_cast<clang::Decl>(decl_ctx)) - { - llvm::raw_string_ostream os(m_dump); - decl->print (os); - os.flush(); - } - else - { - m_dump.assign("<DeclContext is not a Decl>"); - } - + } + + llvm::raw_string_ostream os(m_dump); + decl->print(os); + os.flush(); + + if (decl_ctx) { decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); + } } -ASTDumper::ASTDumper (const clang::Type *type) -{ - m_dump = clang::QualType(type, 0).getAsString(); -} +ASTDumper::ASTDumper(clang::DeclContext *decl_ctx) { + bool has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); + bool has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); -ASTDumper::ASTDumper (clang::QualType type) -{ - m_dump = type.getAsString(); -} + decl_ctx->setHasExternalLexicalStorage(false); + decl_ctx->setHasExternalVisibleStorage(false); + + if (clang::Decl *decl = llvm::dyn_cast<clang::Decl>(decl_ctx)) { + llvm::raw_string_ostream os(m_dump); + decl->print(os); + os.flush(); + } else { + m_dump.assign("<DeclContext is not a Decl>"); + } -ASTDumper::ASTDumper (lldb::opaque_compiler_type_t type) -{ - m_dump = clang::QualType::getFromOpaquePtr(type).getAsString(); + decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); + decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); } -ASTDumper::ASTDumper (const CompilerType &compiler_type) -{ - m_dump = ClangUtil::GetQualType(compiler_type).getAsString(); +ASTDumper::ASTDumper(const clang::Type *type) { + m_dump = clang::QualType(type, 0).getAsString(); } +ASTDumper::ASTDumper(clang::QualType type) { m_dump = type.getAsString(); } -const char * -ASTDumper::GetCString() -{ - return m_dump.c_str(); +ASTDumper::ASTDumper(lldb::opaque_compiler_type_t type) { + m_dump = clang::QualType::getFromOpaquePtr(type).getAsString(); } -void ASTDumper::ToSTDERR() -{ - fprintf(stderr, "%s\n", m_dump.c_str()); +ASTDumper::ASTDumper(const CompilerType &compiler_type) { + m_dump = ClangUtil::GetQualType(compiler_type).getAsString(); } -void ASTDumper::ToLog(Log *log, const char *prefix) -{ - size_t len = m_dump.length() + 1; - - char *alloc = (char*)malloc(len); - char *str = alloc; - - memcpy(str, m_dump.c_str(), len); - - char *end = NULL; - - end = strchr(str, '\n'); - - while (end) - { - *end = '\0'; - - log->Printf("%s%s", prefix, str); - - *end = '\n'; - - str = end + 1; - end = strchr(str, '\n'); - } - +const char *ASTDumper::GetCString() { return m_dump.c_str(); } + +void ASTDumper::ToSTDERR() { fprintf(stderr, "%s\n", m_dump.c_str()); } + +void ASTDumper::ToLog(Log *log, const char *prefix) { + size_t len = m_dump.length() + 1; + + char *alloc = (char *)malloc(len); + char *str = alloc; + + memcpy(str, m_dump.c_str(), len); + + char *end = NULL; + + end = strchr(str, '\n'); + + while (end) { + *end = '\0'; + log->Printf("%s%s", prefix, str); - - free(alloc); + + *end = '\n'; + + str = end + 1; + end = strchr(str, '\n'); + } + + log->Printf("%s%s", prefix, str); + + free(alloc); } -void ASTDumper::ToStream(lldb::StreamSP &stream) -{ - stream->PutCString(m_dump.c_str()); +void ASTDumper::ToStream(lldb::StreamSP &stream) { + stream->PutCString(m_dump.c_str()); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h index c8dc6847d6c..9a72fb64e53 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h @@ -16,25 +16,24 @@ #include "lldb/Core/Stream.h" #include "llvm/ADT/DenseSet.h" -namespace lldb_private -{ - -class ASTDumper -{ +namespace lldb_private { + +class ASTDumper { public: - ASTDumper (clang::Decl *decl); - ASTDumper (clang::DeclContext *decl_ctx); - ASTDumper (const clang::Type *type); - ASTDumper (clang::QualType type); - ASTDumper (lldb::opaque_compiler_type_t type); - ASTDumper (const CompilerType &compiler_type); - - const char *GetCString(); - void ToSTDERR(); - void ToLog(Log *log, const char *prefix); - void ToStream(lldb::StreamSP &stream); + ASTDumper(clang::Decl *decl); + ASTDumper(clang::DeclContext *decl_ctx); + ASTDumper(const clang::Type *type); + ASTDumper(clang::QualType type); + ASTDumper(lldb::opaque_compiler_type_t type); + ASTDumper(const CompilerType &compiler_type); + + const char *GetCString(); + void ToSTDERR(); + void ToLog(Log *log, const char *prefix); + void ToStream(lldb::StreamSP &stream); + private: - std::string m_dump; + std::string m_dump; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index f1231572e26..f8539379f7d 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -33,542 +33,485 @@ using namespace llvm; using namespace clang; using namespace lldb_private; -ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough, bool top_level, Target &target) - : m_ast_context(NULL), - m_passthrough(passthrough), - m_passthrough_sema(NULL), - m_target(target), - m_sema(NULL), - m_top_level(top_level) -{ - if (!m_passthrough) - return; - - m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); +ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough, + bool top_level, Target &target) + : m_ast_context(NULL), m_passthrough(passthrough), m_passthrough_sema(NULL), + m_target(target), m_sema(NULL), m_top_level(top_level) { + if (!m_passthrough) + return; + + m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); } -ASTResultSynthesizer::~ASTResultSynthesizer() -{ -} +ASTResultSynthesizer::~ASTResultSynthesizer() {} -void -ASTResultSynthesizer::Initialize(ASTContext &Context) -{ - m_ast_context = &Context; +void ASTResultSynthesizer::Initialize(ASTContext &Context) { + m_ast_context = &Context; - if (m_passthrough) - m_passthrough->Initialize(Context); + if (m_passthrough) + m_passthrough->Initialize(Context); } -void -ASTResultSynthesizer::TransformTopLevelDecl(Decl* D) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D)) - { - if (log && log->GetVerbose()) - { - if (named_decl->getIdentifier()) - log->Printf("TransformTopLevelDecl(%s)", named_decl->getIdentifier()->getNameStart()); - else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D)) - log->Printf("TransformTopLevelDecl(%s)", method_decl->getSelector().getAsString().c_str()); - else - log->Printf("TransformTopLevelDecl(<complex>)"); - } - - if (m_top_level) - { - RecordPersistentDecl(named_decl); - } +void ASTResultSynthesizer::TransformTopLevelDecl(Decl *D) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D)) { + if (log && log->GetVerbose()) { + if (named_decl->getIdentifier()) + log->Printf("TransformTopLevelDecl(%s)", + named_decl->getIdentifier()->getNameStart()); + else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D)) + log->Printf("TransformTopLevelDecl(%s)", + method_decl->getSelector().getAsString().c_str()); + else + log->Printf("TransformTopLevelDecl(<complex>)"); + } + + if (m_top_level) { + RecordPersistentDecl(named_decl); } + } - if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D)) - { - RecordDecl::decl_iterator decl_iterator; + if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D)) { + RecordDecl::decl_iterator decl_iterator; - for (decl_iterator = linkage_spec_decl->decls_begin(); - decl_iterator != linkage_spec_decl->decls_end(); - ++decl_iterator) - { - TransformTopLevelDecl(*decl_iterator); - } + for (decl_iterator = linkage_spec_decl->decls_begin(); + decl_iterator != linkage_spec_decl->decls_end(); ++decl_iterator) { + TransformTopLevelDecl(*decl_iterator); } - else if (!m_top_level) - { - if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D)) - { - if (m_ast_context && !method_decl->getSelector().getAsString().compare("$__lldb_expr:")) - { - RecordPersistentTypes(method_decl); - SynthesizeObjCMethodResult(method_decl); - } - } - else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D)) - { - if (m_ast_context && !function_decl->getNameInfo().getAsString().compare("$__lldb_expr")) - { - RecordPersistentTypes(function_decl); - SynthesizeFunctionResult(function_decl); - } - } + } else if (!m_top_level) { + if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D)) { + if (m_ast_context && + !method_decl->getSelector().getAsString().compare("$__lldb_expr:")) { + RecordPersistentTypes(method_decl); + SynthesizeObjCMethodResult(method_decl); + } + } else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D)) { + if (m_ast_context && + !function_decl->getNameInfo().getAsString().compare("$__lldb_expr")) { + RecordPersistentTypes(function_decl); + SynthesizeFunctionResult(function_decl); + } } + } } -bool -ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D) -{ - DeclGroupRef::iterator decl_iterator; +bool ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D) { + DeclGroupRef::iterator decl_iterator; - for (decl_iterator = D.begin(); - decl_iterator != D.end(); - ++decl_iterator) - { - Decl *decl = *decl_iterator; + for (decl_iterator = D.begin(); decl_iterator != D.end(); ++decl_iterator) { + Decl *decl = *decl_iterator; - TransformTopLevelDecl(decl); - } + TransformTopLevelDecl(decl); + } - if (m_passthrough) - return m_passthrough->HandleTopLevelDecl(D); - return true; + if (m_passthrough) + return m_passthrough->HandleTopLevelDecl(D); + return true; } -bool -ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool ASTResultSynthesizer::SynthesizeFunctionResult(FunctionDecl *FunDecl) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (!m_sema) - return false; + if (!m_sema) + return false; - FunctionDecl *function_decl = FunDecl; + FunctionDecl *function_decl = FunDecl; - if (!function_decl) - return false; + if (!function_decl) + return false; - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream os(s); + if (log && log->GetVerbose()) { + std::string s; + raw_string_ostream os(s); - function_decl->print(os); + function_decl->print(os); - os.flush(); + os.flush(); - log->Printf ("Untransformed function AST:\n%s", s.c_str()); - } + log->Printf("Untransformed function AST:\n%s", s.c_str()); + } - Stmt *function_body = function_decl->getBody(); - CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body); + Stmt *function_body = function_decl->getBody(); + CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body); - bool ret = SynthesizeBodyResult (compound_stmt, - function_decl); + bool ret = SynthesizeBodyResult(compound_stmt, function_decl); - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream os(s); + if (log && log->GetVerbose()) { + std::string s; + raw_string_ostream os(s); - function_decl->print(os); + function_decl->print(os); - os.flush(); + os.flush(); - log->Printf ("Transformed function AST:\n%s", s.c_str()); - } + log->Printf("Transformed function AST:\n%s", s.c_str()); + } - return ret; + return ret; } -bool -ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool ASTResultSynthesizer::SynthesizeObjCMethodResult( + ObjCMethodDecl *MethodDecl) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (!m_sema) - return false; + if (!m_sema) + return false; - if (!MethodDecl) - return false; + if (!MethodDecl) + return false; - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream os(s); + if (log && log->GetVerbose()) { + std::string s; + raw_string_ostream os(s); - MethodDecl->print(os); + MethodDecl->print(os); - os.flush(); + os.flush(); - log->Printf ("Untransformed method AST:\n%s", s.c_str()); - } + log->Printf("Untransformed method AST:\n%s", s.c_str()); + } - Stmt *method_body = MethodDecl->getBody(); + Stmt *method_body = MethodDecl->getBody(); - if (!method_body) - return false; + if (!method_body) + return false; - CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body); + CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body); - bool ret = SynthesizeBodyResult (compound_stmt, - MethodDecl); + bool ret = SynthesizeBodyResult(compound_stmt, MethodDecl); - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream os(s); + if (log && log->GetVerbose()) { + std::string s; + raw_string_ostream os(s); - MethodDecl->print(os); + MethodDecl->print(os); - os.flush(); + os.flush(); - log->Printf("Transformed method AST:\n%s", s.c_str()); - } + log->Printf("Transformed method AST:\n%s", s.c_str()); + } - return ret; + return ret; } -bool -ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body, - DeclContext *DC) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - ASTContext &Ctx(*m_ast_context); - - if (!Body) - return false; - - if (Body->body_empty()) - return false; - - Stmt **last_stmt_ptr = Body->body_end() - 1; - Stmt *last_stmt = *last_stmt_ptr; - - while (dyn_cast<NullStmt>(last_stmt)) - { - if (last_stmt_ptr != Body->body_begin()) - { - last_stmt_ptr--; - last_stmt = *last_stmt_ptr; - } - else - { - return false; - } - } +bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, + DeclContext *DC) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + ASTContext &Ctx(*m_ast_context); + + if (!Body) + return false; + + if (Body->body_empty()) + return false; + + Stmt **last_stmt_ptr = Body->body_end() - 1; + Stmt *last_stmt = *last_stmt_ptr; - Expr *last_expr = dyn_cast<Expr>(last_stmt); - - if (!last_expr) - // No auxiliary variable necessary; expression returns void - return true; - - // In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off if that's the - // case. - - do { - ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr); - - if (!implicit_cast) - break; - - if (implicit_cast->getCastKind() != CK_LValueToRValue) - break; - - last_expr = implicit_cast->getSubExpr(); - } while (0); - - // is_lvalue is used to record whether the expression returns an assignable Lvalue or an - // Rvalue. This is relevant because they are handled differently. - // - // For Lvalues - // - // - In AST result synthesis (here!) the expression E is transformed into an initialization - // T *$__lldb_expr_result_ptr = &E. - // - // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be - // passed into the expression. - // - // - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at - // an entry in the struct ($__lldb_arg) passed into the expression. (Other persistent - // variables are treated similarly, having been materialized as references, but in those - // cases the value of the reference itself is never modified.) - // - // - During materialization, $0 (the result persistent variable) is ignored. - // - // - During dematerialization, $0 is marked up as a load address with value equal to the - // contents of the structure entry. - // - // For Rvalues - // - // - In AST result synthesis the expression E is transformed into an initialization - // static T $__lldb_expr_result = E. - // - // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be - // passed into the expression. - // - // - In IR transformations, an instruction is inserted at the beginning of the function to - // dereference the pointer resident in the slot. Reads and writes to $__lldb_expr_result - // are redirected at that dereferenced version. Guard variables for the static variable - // are excised. - // - // - During materialization, $0 (the result persistent variable) is populated with the location - // of a newly-allocated area of memory. - // - // - During dematerialization, $0 is ignored. - - bool is_lvalue = - (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) && - (last_expr->getObjectKind() == OK_Ordinary); - - QualType expr_qual_type = last_expr->getType(); - const clang::Type *expr_type = expr_qual_type.getTypePtr(); - - if (!expr_type) - return false; - - if (expr_type->isVoidType()) - return true; - - if (log) - { - std::string s = expr_qual_type.getAsString(); - - log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); + while (dyn_cast<NullStmt>(last_stmt)) { + if (last_stmt_ptr != Body->body_begin()) { + last_stmt_ptr--; + last_stmt = *last_stmt_ptr; + } else { + return false; } + } - clang::VarDecl *result_decl = NULL; + Expr *last_expr = dyn_cast<Expr>(last_stmt); - if (is_lvalue) - { - IdentifierInfo *result_ptr_id; + if (!last_expr) + // No auxiliary variable necessary; expression returns void + return true; - if (expr_type->isFunctionType()) - result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers - else - result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr"); + // In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off + // if that's the + // case. + + do { + ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr); + + if (!implicit_cast) + break; + + if (implicit_cast->getCastKind() != CK_LValueToRValue) + break; + + last_expr = implicit_cast->getSubExpr(); + } while (0); + + // is_lvalue is used to record whether the expression returns an assignable + // Lvalue or an + // Rvalue. This is relevant because they are handled differently. + // + // For Lvalues + // + // - In AST result synthesis (here!) the expression E is transformed into an + // initialization + // T *$__lldb_expr_result_ptr = &E. + // + // - In structure allocation, a pointer-sized slot is allocated in the + // struct that is to be + // passed into the expression. + // + // - In IR transformations, reads and writes to $__lldb_expr_result_ptr are + // redirected at + // an entry in the struct ($__lldb_arg) passed into the expression. + // (Other persistent + // variables are treated similarly, having been materialized as + // references, but in those + // cases the value of the reference itself is never modified.) + // + // - During materialization, $0 (the result persistent variable) is ignored. + // + // - During dematerialization, $0 is marked up as a load address with value + // equal to the + // contents of the structure entry. + // + // For Rvalues + // + // - In AST result synthesis the expression E is transformed into an + // initialization + // static T $__lldb_expr_result = E. + // + // - In structure allocation, a pointer-sized slot is allocated in the + // struct that is to be + // passed into the expression. + // + // - In IR transformations, an instruction is inserted at the beginning of + // the function to + // dereference the pointer resident in the slot. Reads and writes to + // $__lldb_expr_result + // are redirected at that dereferenced version. Guard variables for the + // static variable + // are excised. + // + // - During materialization, $0 (the result persistent variable) is + // populated with the location + // of a newly-allocated area of memory. + // + // - During dematerialization, $0 is ignored. + + bool is_lvalue = (last_expr->getValueKind() == VK_LValue || + last_expr->getValueKind() == VK_XValue) && + (last_expr->getObjectKind() == OK_Ordinary); + + QualType expr_qual_type = last_expr->getType(); + const clang::Type *expr_type = expr_qual_type.getTypePtr(); + + if (!expr_type) + return false; + + if (expr_type->isVoidType()) + return true; - m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, clang::diag::err_incomplete_type); + if (log) { + std::string s = expr_qual_type.getAsString(); - QualType ptr_qual_type; + log->Printf("Last statement is an %s with type: %s", + (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); + } - if (expr_qual_type->getAs<ObjCObjectType>() != NULL) - ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type); - else - ptr_qual_type = Ctx.getPointerType(expr_qual_type); + clang::VarDecl *result_decl = NULL; - result_decl = VarDecl::Create(Ctx, - DC, - SourceLocation(), - SourceLocation(), - result_ptr_id, - ptr_qual_type, - NULL, - SC_Static); + if (is_lvalue) { + IdentifierInfo *result_ptr_id; - if (!result_decl) - return false; + if (expr_type->isFunctionType()) + result_ptr_id = + &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should + // be treated like function + // pointers + else + result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr"); - ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr); - if (address_of_expr.get()) - m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(), true, false); - else - return false; - } + m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, + clang::diag::err_incomplete_type); + + QualType ptr_qual_type; + + if (expr_qual_type->getAs<ObjCObjectType>() != NULL) + ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type); else - { - IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result"); - - result_decl = VarDecl::Create(Ctx, - DC, - SourceLocation(), - SourceLocation(), - &result_id, - expr_qual_type, - NULL, - SC_Static); - - if (!result_decl) - return false; - - m_sema->AddInitializerToDecl(result_decl, last_expr, true, false); - } + ptr_qual_type = Ctx.getPointerType(expr_qual_type); + + result_decl = + VarDecl::Create(Ctx, DC, SourceLocation(), SourceLocation(), + result_ptr_id, ptr_qual_type, NULL, SC_Static); - DC->addDecl(result_decl); + if (!result_decl) + return false; - /////////////////////////////// - // call AddInitializerToDecl - // + ExprResult address_of_expr = + m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr); + if (address_of_expr.get()) + m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(), true, + false); + else + return false; + } else { + IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result"); - //m_sema->AddInitializerToDecl(result_decl, last_expr); + result_decl = VarDecl::Create(Ctx, DC, SourceLocation(), SourceLocation(), + &result_id, expr_qual_type, NULL, SC_Static); - ///////////////////////////////// - // call ConvertDeclToDeclGroup - // + if (!result_decl) + return false; - Sema::DeclGroupPtrTy result_decl_group_ptr; + m_sema->AddInitializerToDecl(result_decl, last_expr, true, false); + } - result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl); + DC->addDecl(result_decl); - //////////////////////// - // call ActOnDeclStmt - // + /////////////////////////////// + // call AddInitializerToDecl + // - StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(result_decl_group_ptr, - SourceLocation(), - SourceLocation())); + // m_sema->AddInitializerToDecl(result_decl, last_expr); - //////////////////////////////////////////////// - // replace the old statement with the new one - // + ///////////////////////////////// + // call ConvertDeclToDeclGroup + // - *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.get()); + Sema::DeclGroupPtrTy result_decl_group_ptr; - return true; + result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl); + + //////////////////////// + // call ActOnDeclStmt + // + + StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt( + result_decl_group_ptr, SourceLocation(), SourceLocation())); + + //////////////////////////////////////////////// + // replace the old statement with the new one + // + + *last_stmt_ptr = + reinterpret_cast<Stmt *>(result_initialization_stmt_result.get()); + + return true; } -void -ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx) -{ - if (m_passthrough) - m_passthrough->HandleTranslationUnit(Ctx); +void ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx) { + if (m_passthrough) + m_passthrough->HandleTranslationUnit(Ctx); } -void -ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx) -{ - typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator; - - for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()), - e = TypeDeclIterator(FunDeclCtx->decls_end()); - i != e; - ++i) - { - MaybeRecordPersistentType(*i); - } +void ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx) { + typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator; + + for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()), + e = TypeDeclIterator(FunDeclCtx->decls_end()); + i != e; ++i) { + MaybeRecordPersistentType(*i); + } } -void -ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D) -{ - if (!D->getIdentifier()) - return; +void ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D) { + if (!D->getIdentifier()) + return; - StringRef name = D->getName(); + StringRef name = D->getName(); - if (name.size() == 0 || name[0] != '$') - return; + if (name.size() == 0 || name[0] != '$') + return; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - ConstString name_cs(name.str().c_str()); + ConstString name_cs(name.str().c_str()); - if (log) - log->Printf("Recording persistent type %s\n", name_cs.GetCString()); + if (log) + log->Printf("Recording persistent type %s\n", name_cs.GetCString()); - m_decls.push_back(D); + m_decls.push_back(D); } -void -ASTResultSynthesizer::RecordPersistentDecl(NamedDecl *D) -{ - lldbassert(m_top_level); +void ASTResultSynthesizer::RecordPersistentDecl(NamedDecl *D) { + lldbassert(m_top_level); - if (!D->getIdentifier()) - return; + if (!D->getIdentifier()) + return; - StringRef name = D->getName(); + StringRef name = D->getName(); - if (name.size() == 0) - return; + if (name.size() == 0) + return; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - ConstString name_cs(name.str().c_str()); + ConstString name_cs(name.str().c_str()); - if (log) - log->Printf("Recording persistent decl %s\n", name_cs.GetCString()); + if (log) + log->Printf("Recording persistent decl %s\n", name_cs.GetCString()); - m_decls.push_back(D); + m_decls.push_back(D); } -void -ASTResultSynthesizer::CommitPersistentDecls() -{ - for (clang::NamedDecl *decl : m_decls) - { - StringRef name = decl->getName(); - ConstString name_cs(name.str().c_str()); - - Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl( - m_target.GetScratchClangASTContext()->getASTContext(), m_ast_context, decl); - - if (!D_scratch) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - { - std::string s; - llvm::raw_string_ostream ss(s); - decl->dump(ss); - ss.flush(); - - log->Printf("Couldn't commit persistent decl: %s\n", s.c_str()); - } - - continue; - } - - if (NamedDecl *NamedDecl_scratch = dyn_cast<NamedDecl>(D_scratch)) - llvm::cast<ClangPersistentVariables>(m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)) - ->RegisterPersistentDecl(name_cs, NamedDecl_scratch); +void ASTResultSynthesizer::CommitPersistentDecls() { + for (clang::NamedDecl *decl : m_decls) { + StringRef name = decl->getName(); + ConstString name_cs(name.str().c_str()); + + Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl( + m_target.GetScratchClangASTContext()->getASTContext(), m_ast_context, + decl); + + if (!D_scratch) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) { + std::string s; + llvm::raw_string_ostream ss(s); + decl->dump(ss); + ss.flush(); + + log->Printf("Couldn't commit persistent decl: %s\n", s.c_str()); + } + + continue; } + + if (NamedDecl *NamedDecl_scratch = dyn_cast<NamedDecl>(D_scratch)) + llvm::cast<ClangPersistentVariables>( + m_target.GetPersistentExpressionStateForLanguage( + lldb::eLanguageTypeC)) + ->RegisterPersistentDecl(name_cs, NamedDecl_scratch); + } } -void -ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D) -{ - if (m_passthrough) - m_passthrough->HandleTagDeclDefinition(D); +void ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D) { + if (m_passthrough) + m_passthrough->HandleTagDeclDefinition(D); } -void -ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D) -{ - if (m_passthrough) - m_passthrough->CompleteTentativeDefinition(D); +void ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D) { + if (m_passthrough) + m_passthrough->CompleteTentativeDefinition(D); } -void -ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD) -{ - if (m_passthrough) - m_passthrough->HandleVTable(RD); +void ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD) { + if (m_passthrough) + m_passthrough->HandleVTable(RD); } -void -ASTResultSynthesizer::PrintStats() -{ - if (m_passthrough) - m_passthrough->PrintStats(); +void ASTResultSynthesizer::PrintStats() { + if (m_passthrough) + m_passthrough->PrintStats(); } -void -ASTResultSynthesizer::InitializeSema(Sema &S) -{ - m_sema = &S; +void ASTResultSynthesizer::InitializeSema(Sema &S) { + m_sema = &S; - if (m_passthrough_sema) - m_passthrough_sema->InitializeSema(S); + if (m_passthrough_sema) + m_passthrough_sema->InitializeSema(S); } -void -ASTResultSynthesizer::ForgetSema() -{ - m_sema = NULL; +void ASTResultSynthesizer::ForgetSema() { + m_sema = NULL; - if (m_passthrough_sema) - m_passthrough_sema->ForgetSema(); + if (m_passthrough_sema) + m_passthrough_sema->ForgetSema(); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h index 4556713e993..c0e6c0358a2 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h @@ -10,201 +10,204 @@ #ifndef liblldb_ASTResultSynthesizer_h_ #define liblldb_ASTResultSynthesizer_h_ -#include "clang/Sema/SemaConsumer.h" #include "lldb/Core/ClangForward.h" #include "lldb/Target/Target.h" +#include "clang/Sema/SemaConsumer.h" namespace lldb_private { //---------------------------------------------------------------------- -/// @class ASTResultSynthesizer ASTResultSynthesizer.h "lldb/Expression/ASTResultSynthesizer.h" +/// @class ASTResultSynthesizer ASTResultSynthesizer.h +/// "lldb/Expression/ASTResultSynthesizer.h" /// @brief Adds a result variable declaration to the ASTs for an expression. /// /// Users expect the expression "i + 3" to return a result, even if a result -/// variable wasn't specifically declared. To fulfil this requirement, LLDB adds -/// a result variable to the expression, transforming it to +/// variable wasn't specifically declared. To fulfil this requirement, LLDB +/// adds +/// a result variable to the expression, transforming it to /// "int $__lldb_expr_result = i + 3." The IR transformers ensure that the /// resulting variable is mapped to the right piece of memory. /// ASTResultSynthesizer's job is to add the variable and its initialization to /// the ASTs for the expression, and it does so by acting as a SemaConsumer for /// Clang. //---------------------------------------------------------------------- -class ASTResultSynthesizer : public clang::SemaConsumer -{ +class ASTResultSynthesizer : public clang::SemaConsumer { public: - //---------------------------------------------------------------------- - /// Constructor - /// - /// @param[in] passthrough - /// Since the ASTs must typically go through to the Clang code generator - /// in order to produce LLVM IR, this SemaConsumer must allow them to - /// pass to the next step in the chain after processing. Passthrough is - /// the next ASTConsumer, or NULL if none is required. - /// - /// @param[in] top_level - /// If true, register all top-level Decls and don't try to handle the - /// main function. - /// - /// @param[in] target - /// The target, which contains the persistent variable store and the - /// AST importer. - //---------------------------------------------------------------------- - ASTResultSynthesizer(clang::ASTConsumer *passthrough, bool top_level, Target &target); - - //---------------------------------------------------------------------- - /// Destructor - //---------------------------------------------------------------------- - ~ASTResultSynthesizer() override; - - //---------------------------------------------------------------------- - /// Link this consumer with a particular AST context - /// - /// @param[in] Context - /// This AST context will be used for types and identifiers, and also - /// forwarded to the passthrough consumer, if one exists. - //---------------------------------------------------------------------- - void Initialize(clang::ASTContext &Context) override; - - //---------------------------------------------------------------------- - /// Examine a list of Decls to find the function $__lldb_expr and - /// transform its code - /// - /// @param[in] D - /// The list of Decls to search. These may contain LinkageSpecDecls, - /// which need to be searched recursively. That job falls to - /// TransformTopLevelDecl. - //---------------------------------------------------------------------- - bool HandleTopLevelDecl(clang::DeclGroupRef D) override; - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleTranslationUnit(clang::ASTContext &Ctx) override; - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleTagDeclDefinition(clang::TagDecl *D) override; - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void CompleteTentativeDefinition(clang::VarDecl *D) override; - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleVTable(clang::CXXRecordDecl *RD) override; - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void PrintStats() override; - - //---------------------------------------------------------------------- - /// Set the Sema object to use when performing transforms, and pass it on - /// - /// @param[in] S - /// The Sema to use. Because Sema isn't externally visible, this class - /// casts it to an Action for actual use. - //---------------------------------------------------------------------- - void InitializeSema(clang::Sema &S) override; - - //---------------------------------------------------------------------- - /// Reset the Sema to NULL now that transformations are done - //---------------------------------------------------------------------- - void - ForgetSema() override; - - //---------------------------------------------------------------------- - /// The parse has succeeded, so record its persistent decls - //---------------------------------------------------------------------- - void - CommitPersistentDecls(); + //---------------------------------------------------------------------- + /// Constructor + /// + /// @param[in] passthrough + /// Since the ASTs must typically go through to the Clang code generator + /// in order to produce LLVM IR, this SemaConsumer must allow them to + /// pass to the next step in the chain after processing. Passthrough is + /// the next ASTConsumer, or NULL if none is required. + /// + /// @param[in] top_level + /// If true, register all top-level Decls and don't try to handle the + /// main function. + /// + /// @param[in] target + /// The target, which contains the persistent variable store and the + /// AST importer. + //---------------------------------------------------------------------- + ASTResultSynthesizer(clang::ASTConsumer *passthrough, bool top_level, + Target &target); + + //---------------------------------------------------------------------- + /// Destructor + //---------------------------------------------------------------------- + ~ASTResultSynthesizer() override; + + //---------------------------------------------------------------------- + /// Link this consumer with a particular AST context + /// + /// @param[in] Context + /// This AST context will be used for types and identifiers, and also + /// forwarded to the passthrough consumer, if one exists. + //---------------------------------------------------------------------- + void Initialize(clang::ASTContext &Context) override; + + //---------------------------------------------------------------------- + /// Examine a list of Decls to find the function $__lldb_expr and + /// transform its code + /// + /// @param[in] D + /// The list of Decls to search. These may contain LinkageSpecDecls, + /// which need to be searched recursively. That job falls to + /// TransformTopLevelDecl. + //---------------------------------------------------------------------- + bool HandleTopLevelDecl(clang::DeclGroupRef D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTranslationUnit(clang::ASTContext &Ctx) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTagDeclDefinition(clang::TagDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void CompleteTentativeDefinition(clang::VarDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleVTable(clang::CXXRecordDecl *RD) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void PrintStats() override; + + //---------------------------------------------------------------------- + /// Set the Sema object to use when performing transforms, and pass it on + /// + /// @param[in] S + /// The Sema to use. Because Sema isn't externally visible, this class + /// casts it to an Action for actual use. + //---------------------------------------------------------------------- + void InitializeSema(clang::Sema &S) override; + + //---------------------------------------------------------------------- + /// Reset the Sema to NULL now that transformations are done + //---------------------------------------------------------------------- + void ForgetSema() override; + + //---------------------------------------------------------------------- + /// The parse has succeeded, so record its persistent decls + //---------------------------------------------------------------------- + void CommitPersistentDecls(); private: - //---------------------------------------------------------------------- - /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing - /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on - /// anything that was found - /// - /// @param[in] D - /// The Decl to hunt. - //---------------------------------------------------------------------- - void TransformTopLevelDecl(clang::Decl *D); - - //---------------------------------------------------------------------- - /// Process an Objective-C method and produce the result variable and - /// initialization - /// - /// @param[in] MethodDecl - /// The method to process. - //---------------------------------------------------------------------- - bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl); - - //---------------------------------------------------------------------- - /// Process a function and produce the result variable and initialization - /// - /// @param[in] FunDecl - /// The function to process. - //---------------------------------------------------------------------- - bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl); - - //---------------------------------------------------------------------- - /// Process a function body and produce the result variable and - /// initialization - /// - /// @param[in] Body - /// The body of the function. - /// - /// @param[in] DC - /// The DeclContext of the function, into which the result variable - /// is inserted. - //---------------------------------------------------------------------- - bool SynthesizeBodyResult(clang::CompoundStmt *Body, - clang::DeclContext *DC); - - //---------------------------------------------------------------------- - /// Given a DeclContext for a function or method, find all types - /// declared in the context and record any persistent types found. - /// - /// @param[in] FunDeclCtx - /// The context for the function to process. - //---------------------------------------------------------------------- - void RecordPersistentTypes(clang::DeclContext *FunDeclCtx); - - //---------------------------------------------------------------------- - /// Given a TypeDecl, if it declares a type whose name starts with a - /// dollar sign, register it as a pointer type in the target's scratch - /// AST context. - /// - /// @param[in] Body - /// The body of the function. - //---------------------------------------------------------------------- - void - MaybeRecordPersistentType(clang::TypeDecl *D); - - //---------------------------------------------------------------------- - /// Given a NamedDecl, register it as a pointer type in the target's scratch - /// AST context. - /// - /// @param[in] Body - /// The body of the function. - //---------------------------------------------------------------------- - void - RecordPersistentDecl(clang::NamedDecl *D); - - clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types. - clang::ASTConsumer - *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer. - clang::SemaConsumer - *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer. - - std::vector<clang::NamedDecl *> m_decls; ///< Persistent declarations to register assuming the expression succeeds. - - Target &m_target; ///< The target, which contains the persistent variable store and the - clang::Sema *m_sema; ///< The Sema to use. - bool m_top_level; + //---------------------------------------------------------------------- + /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing + /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on + /// anything that was found + /// + /// @param[in] D + /// The Decl to hunt. + //---------------------------------------------------------------------- + void TransformTopLevelDecl(clang::Decl *D); + + //---------------------------------------------------------------------- + /// Process an Objective-C method and produce the result variable and + /// initialization + /// + /// @param[in] MethodDecl + /// The method to process. + //---------------------------------------------------------------------- + bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl); + + //---------------------------------------------------------------------- + /// Process a function and produce the result variable and initialization + /// + /// @param[in] FunDecl + /// The function to process. + //---------------------------------------------------------------------- + bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl); + + //---------------------------------------------------------------------- + /// Process a function body and produce the result variable and + /// initialization + /// + /// @param[in] Body + /// The body of the function. + /// + /// @param[in] DC + /// The DeclContext of the function, into which the result variable + /// is inserted. + //---------------------------------------------------------------------- + bool SynthesizeBodyResult(clang::CompoundStmt *Body, clang::DeclContext *DC); + + //---------------------------------------------------------------------- + /// Given a DeclContext for a function or method, find all types + /// declared in the context and record any persistent types found. + /// + /// @param[in] FunDeclCtx + /// The context for the function to process. + //---------------------------------------------------------------------- + void RecordPersistentTypes(clang::DeclContext *FunDeclCtx); + + //---------------------------------------------------------------------- + /// Given a TypeDecl, if it declares a type whose name starts with a + /// dollar sign, register it as a pointer type in the target's scratch + /// AST context. + /// + /// @param[in] Body + /// The body of the function. + //---------------------------------------------------------------------- + void MaybeRecordPersistentType(clang::TypeDecl *D); + + //---------------------------------------------------------------------- + /// Given a NamedDecl, register it as a pointer type in the target's scratch + /// AST context. + /// + /// @param[in] Body + /// The body of the function. + //---------------------------------------------------------------------- + void RecordPersistentDecl(clang::NamedDecl *D); + + clang::ASTContext + *m_ast_context; ///< The AST context to use for identifiers and types. + clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for + ///passthrough. NULL if it's a + ///SemaConsumer. + clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, + ///for passthrough. NULL if it's an + ///ASTConsumer. + + std::vector<clang::NamedDecl *> m_decls; ///< Persistent declarations to + ///register assuming the expression + ///succeeds. + + Target &m_target; ///< The target, which contains the persistent variable + ///store and the + clang::Sema *m_sema; ///< The Sema to use. + bool m_top_level; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp index 38a2b6b33a8..4081bc990c9 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp @@ -9,6 +9,7 @@ #include "ASTStructExtractor.h" +#include "lldb/Core/Log.h" #include "stdlib.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" @@ -21,7 +22,6 @@ #include "clang/Sema/Sema.h" #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" -#include "lldb/Core/Log.h" using namespace llvm; using namespace clang; @@ -29,193 +29,158 @@ using namespace lldb_private; ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, const char *struct_name, - ClangFunctionCaller &function) : - m_ast_context (NULL), - m_passthrough (passthrough), - m_passthrough_sema (NULL), - m_sema (NULL), - m_action (NULL), - m_function (function), - m_struct_name (struct_name) -{ - if (!m_passthrough) - return; - - m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); + ClangFunctionCaller &function) + : m_ast_context(NULL), m_passthrough(passthrough), m_passthrough_sema(NULL), + m_sema(NULL), m_action(NULL), m_function(function), + m_struct_name(struct_name) { + if (!m_passthrough) + return; + + m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); } -ASTStructExtractor::~ASTStructExtractor() -{ -} +ASTStructExtractor::~ASTStructExtractor() {} -void -ASTStructExtractor::Initialize(ASTContext &Context) -{ - m_ast_context = &Context; +void ASTStructExtractor::Initialize(ASTContext &Context) { + m_ast_context = &Context; - if (m_passthrough) - m_passthrough->Initialize(Context); + if (m_passthrough) + m_passthrough->Initialize(Context); } -void -ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) -{ - if (!F->hasBody()) - return; - - Stmt *body_stmt = F->getBody(); - CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt); - - if (!body_compound_stmt) - return; // do we have to handle this? - - RecordDecl *struct_decl = NULL; - - StringRef desired_name(m_struct_name.c_str()); - - for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), be = body_compound_stmt->body_end(); - bi != be; - ++bi) - { - Stmt *curr_stmt = *bi; - DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt); - if (!curr_decl_stmt) - continue; - DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); - for (Decl *candidate_decl : decl_group) - { - RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl); - if (!candidate_record_decl) - continue; - if (candidate_record_decl->getName() == desired_name) - { - struct_decl = candidate_record_decl; - break; - } - } - if (struct_decl) - break; +void ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) { + if (!F->hasBody()) + return; + + Stmt *body_stmt = F->getBody(); + CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt); + + if (!body_compound_stmt) + return; // do we have to handle this? + + RecordDecl *struct_decl = NULL; + + StringRef desired_name(m_struct_name.c_str()); + + for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), + be = body_compound_stmt->body_end(); + bi != be; ++bi) { + Stmt *curr_stmt = *bi; + DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt); + if (!curr_decl_stmt) + continue; + DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); + for (Decl *candidate_decl : decl_group) { + RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl); + if (!candidate_record_decl) + continue; + if (candidate_record_decl->getName() == desired_name) { + struct_decl = candidate_record_decl; + break; + } } + if (struct_decl) + break; + } + + if (!struct_decl) + return; + + const ASTRecordLayout *struct_layout( + &m_ast_context->getASTRecordLayout(struct_decl)); + + if (!struct_layout) + return; + + m_function.m_struct_size = + struct_layout->getSize() + .getQuantity(); // TODO Store m_struct_size as CharUnits + m_function.m_return_offset = + struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; + m_function.m_return_size = + struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; + + for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); + field_index < num_fields; ++field_index) { + m_function.m_member_offsets.push_back( + struct_layout->getFieldOffset(field_index) / 8); + } + + m_function.m_struct_valid = true; +} - if (!struct_decl) - return; - - const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl)); - - if (!struct_layout) - return; - - m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits - m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; - m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; - - for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); - field_index < num_fields; - ++field_index) - { - m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8); - } +void ASTStructExtractor::ExtractFromTopLevelDecl(Decl *D) { + LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D); - m_function.m_struct_valid = true; -} + if (linkage_spec_decl) { + RecordDecl::decl_iterator decl_iterator; -void -ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D) -{ - LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D); - - if (linkage_spec_decl) - { - RecordDecl::decl_iterator decl_iterator; - - for (decl_iterator = linkage_spec_decl->decls_begin(); - decl_iterator != linkage_spec_decl->decls_end(); - ++decl_iterator) - { - ExtractFromTopLevelDecl(*decl_iterator); - } + for (decl_iterator = linkage_spec_decl->decls_begin(); + decl_iterator != linkage_spec_decl->decls_end(); ++decl_iterator) { + ExtractFromTopLevelDecl(*decl_iterator); } + } - FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D); + FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D); - if (m_ast_context && - function_decl && - !m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str())) - { - ExtractFromFunctionDecl(function_decl); - } + if (m_ast_context && function_decl && + !m_function.m_wrapper_function_name.compare( + function_decl->getNameAsString().c_str())) { + ExtractFromFunctionDecl(function_decl); + } } -bool -ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) -{ - DeclGroupRef::iterator decl_iterator; +bool ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) { + DeclGroupRef::iterator decl_iterator; - for (decl_iterator = D.begin(); - decl_iterator != D.end(); - ++decl_iterator) - { - Decl *decl = *decl_iterator; + for (decl_iterator = D.begin(); decl_iterator != D.end(); ++decl_iterator) { + Decl *decl = *decl_iterator; - ExtractFromTopLevelDecl(decl); - } + ExtractFromTopLevelDecl(decl); + } - if (m_passthrough) - return m_passthrough->HandleTopLevelDecl(D); - return true; + if (m_passthrough) + return m_passthrough->HandleTopLevelDecl(D); + return true; } -void -ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) -{ - if (m_passthrough) - m_passthrough->HandleTranslationUnit(Ctx); +void ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) { + if (m_passthrough) + m_passthrough->HandleTranslationUnit(Ctx); } -void -ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) -{ - if (m_passthrough) - m_passthrough->HandleTagDeclDefinition(D); +void ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) { + if (m_passthrough) + m_passthrough->HandleTagDeclDefinition(D); } -void -ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) -{ - if (m_passthrough) - m_passthrough->CompleteTentativeDefinition(D); +void ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) { + if (m_passthrough) + m_passthrough->CompleteTentativeDefinition(D); } -void -ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) -{ - if (m_passthrough) - m_passthrough->HandleVTable(RD); +void ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) { + if (m_passthrough) + m_passthrough->HandleVTable(RD); } -void -ASTStructExtractor::PrintStats() -{ - if (m_passthrough) - m_passthrough->PrintStats(); +void ASTStructExtractor::PrintStats() { + if (m_passthrough) + m_passthrough->PrintStats(); } -void -ASTStructExtractor::InitializeSema(Sema &S) -{ - m_sema = &S; - m_action = reinterpret_cast<Action*>(m_sema); +void ASTStructExtractor::InitializeSema(Sema &S) { + m_sema = &S; + m_action = reinterpret_cast<Action *>(m_sema); - if (m_passthrough_sema) - m_passthrough_sema->InitializeSema(S); + if (m_passthrough_sema) + m_passthrough_sema->InitializeSema(S); } -void -ASTStructExtractor::ForgetSema() -{ - m_sema = NULL; - m_action = NULL; +void ASTStructExtractor::ForgetSema() { + m_sema = NULL; + m_action = NULL; - if (m_passthrough_sema) - m_passthrough_sema->ForgetSema(); + if (m_passthrough_sema) + m_passthrough_sema->ForgetSema(); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h index 2152cff911f..63e3161cae8 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h @@ -13,16 +13,18 @@ #include "ClangExpressionVariable.h" #include "ClangFunctionCaller.h" -#include "clang/Sema/SemaConsumer.h" #include "lldb/Core/ClangForward.h" +#include "clang/Sema/SemaConsumer.h" namespace lldb_private { - + //---------------------------------------------------------------------- -/// @class ASTStructExtractor ASTStructExtractor.h "lldb/Expression/ASTStructExtractor.h" +/// @class ASTStructExtractor ASTStructExtractor.h +/// "lldb/Expression/ASTStructExtractor.h" /// @brief Extracts and describes the argument structure for a wrapped function. /// -/// This pass integrates with ClangFunctionCaller, which calls functions with custom +/// This pass integrates with ClangFunctionCaller, which calls functions with +/// custom /// sets of arguments. To avoid having to implement the full calling convention /// for the target's architecture, ClangFunctionCaller writes a simple wrapper /// function that takes a pointer to an argument structure that contains room @@ -33,126 +35,130 @@ namespace lldb_private { /// so Clang does the structure layout itself. ASTStructExtractor reads through /// the AST for the wrapper function and finds the struct. //---------------------------------------------------------------------- -class ASTStructExtractor : public clang::SemaConsumer -{ +class ASTStructExtractor : public clang::SemaConsumer { public: - //---------------------------------------------------------------------- - /// Constructor - /// - /// @param[in] passthrough - /// Since the ASTs must typically go through to the Clang code generator - /// in order to produce LLVM IR, this SemaConsumer must allow them to - /// pass to the next step in the chain after processing. Passthrough is - /// the next ASTConsumer, or NULL if none is required. - /// - /// @param[in] struct_name - /// The name of the structure to extract from the wrapper function. - /// - /// @param[in] function - /// The caller object whose members should be populated with information - /// about the argument struct. ClangFunctionCaller friends ASTStructExtractor - /// for this purpose. - //---------------------------------------------------------------------- - ASTStructExtractor(clang::ASTConsumer *passthrough, - const char *struct_name, - ClangFunctionCaller &function); - - //---------------------------------------------------------------------- - /// Destructor - //---------------------------------------------------------------------- - ~ASTStructExtractor() override; - - //---------------------------------------------------------------------- - /// Link this consumer with a particular AST context - /// - /// @param[in] Context - /// This AST context will be used for types and identifiers, and also - /// forwarded to the passthrough consumer, if one exists. - //---------------------------------------------------------------------- - void Initialize(clang::ASTContext &Context) override; - - //---------------------------------------------------------------------- - /// Examine a list of Decls to find the function $__lldb_expr and - /// transform its code - /// - /// @param[in] D - /// The list of Decls to search. These may contain LinkageSpecDecls, - /// which need to be searched recursively. That job falls to - /// TransformTopLevelDecl. - //---------------------------------------------------------------------- - bool HandleTopLevelDecl(clang::DeclGroupRef D) override; - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleTranslationUnit(clang::ASTContext &Ctx) override; - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleTagDeclDefinition(clang::TagDecl *D) override; - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void CompleteTentativeDefinition(clang::VarDecl *D) override; - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleVTable(clang::CXXRecordDecl *RD) override; - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void PrintStats() override; - - //---------------------------------------------------------------------- - /// Set the Sema object to use when performing transforms, and pass it on - /// - /// @param[in] S - /// The Sema to use. Because Sema isn't externally visible, this class - /// casts it to an Action for actual use. - //---------------------------------------------------------------------- - void InitializeSema(clang::Sema &S) override; - - //---------------------------------------------------------------------- - /// Reset the Sema to NULL now that transformations are done - //---------------------------------------------------------------------- - void ForgetSema() override; + //---------------------------------------------------------------------- + /// Constructor + /// + /// @param[in] passthrough + /// Since the ASTs must typically go through to the Clang code generator + /// in order to produce LLVM IR, this SemaConsumer must allow them to + /// pass to the next step in the chain after processing. Passthrough is + /// the next ASTConsumer, or NULL if none is required. + /// + /// @param[in] struct_name + /// The name of the structure to extract from the wrapper function. + /// + /// @param[in] function + /// The caller object whose members should be populated with information + /// about the argument struct. ClangFunctionCaller friends + /// ASTStructExtractor + /// for this purpose. + //---------------------------------------------------------------------- + ASTStructExtractor(clang::ASTConsumer *passthrough, const char *struct_name, + ClangFunctionCaller &function); + + //---------------------------------------------------------------------- + /// Destructor + //---------------------------------------------------------------------- + ~ASTStructExtractor() override; + + //---------------------------------------------------------------------- + /// Link this consumer with a particular AST context + /// + /// @param[in] Context + /// This AST context will be used for types and identifiers, and also + /// forwarded to the passthrough consumer, if one exists. + //---------------------------------------------------------------------- + void Initialize(clang::ASTContext &Context) override; + + //---------------------------------------------------------------------- + /// Examine a list of Decls to find the function $__lldb_expr and + /// transform its code + /// + /// @param[in] D + /// The list of Decls to search. These may contain LinkageSpecDecls, + /// which need to be searched recursively. That job falls to + /// TransformTopLevelDecl. + //---------------------------------------------------------------------- + bool HandleTopLevelDecl(clang::DeclGroupRef D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTranslationUnit(clang::ASTContext &Ctx) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTagDeclDefinition(clang::TagDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void CompleteTentativeDefinition(clang::VarDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleVTable(clang::CXXRecordDecl *RD) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void PrintStats() override; + + //---------------------------------------------------------------------- + /// Set the Sema object to use when performing transforms, and pass it on + /// + /// @param[in] S + /// The Sema to use. Because Sema isn't externally visible, this class + /// casts it to an Action for actual use. + //---------------------------------------------------------------------- + void InitializeSema(clang::Sema &S) override; + + //---------------------------------------------------------------------- + /// Reset the Sema to NULL now that transformations are done + //---------------------------------------------------------------------- + void ForgetSema() override; private: - //---------------------------------------------------------------------- - /// Hunt the given FunctionDecl for the argument struct and place - /// information about it into m_function - /// - /// @param[in] F - /// The FunctionDecl to hunt. - //---------------------------------------------------------------------- - void - ExtractFromFunctionDecl(clang::FunctionDecl* F); - - //---------------------------------------------------------------------- - /// Hunt the given Decl for FunctionDecls named the same as the wrapper - /// function name, recursing as necessary through LinkageSpecDecls, and - /// calling ExtractFromFunctionDecl on anything that was found - /// - /// @param[in] D - /// The Decl to hunt. - //---------------------------------------------------------------------- - void - ExtractFromTopLevelDecl(clang::Decl* D); - - clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types. - clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer. - clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer. - clang::Sema *m_sema; ///< The Sema to use. - clang::Action *m_action; ///< The Sema to use, cast to an Action so it's usable. - - ClangFunctionCaller &m_function; ///< The function to populate with information about the argument structure. - std::string m_struct_name; ///< The name of the structure to extract. + //---------------------------------------------------------------------- + /// Hunt the given FunctionDecl for the argument struct and place + /// information about it into m_function + /// + /// @param[in] F + /// The FunctionDecl to hunt. + //---------------------------------------------------------------------- + void ExtractFromFunctionDecl(clang::FunctionDecl *F); + + //---------------------------------------------------------------------- + /// Hunt the given Decl for FunctionDecls named the same as the wrapper + /// function name, recursing as necessary through LinkageSpecDecls, and + /// calling ExtractFromFunctionDecl on anything that was found + /// + /// @param[in] D + /// The Decl to hunt. + //---------------------------------------------------------------------- + void ExtractFromTopLevelDecl(clang::Decl *D); + + clang::ASTContext + *m_ast_context; ///< The AST context to use for identifiers and types. + clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for + ///passthrough. NULL if it's a + ///SemaConsumer. + clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, + ///for passthrough. NULL if it's an + ///ASTConsumer. + clang::Sema *m_sema; ///< The Sema to use. + clang::Action + *m_action; ///< The Sema to use, cast to an Action so it's usable. + + ClangFunctionCaller &m_function; ///< The function to populate with + ///information about the argument structure. + std::string m_struct_name; ///< The name of the structure to extract. }; - + } // namespace lldb_private #endif // liblldb_ASTStructExtractor_h_ diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index def0d42d32d..7a5f4f7a192 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -1,4 +1,5 @@ -//===-- ClangASTSource.cpp ---------------------------------------*- C++ -*-===// +//===-- ClangASTSource.cpp ---------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -37,884 +38,833 @@ using namespace lldb_private; // when it goes out of scope. //------------------------------------------------------------------ namespace { - class ScopedLexicalDeclEraser - { - public: - ScopedLexicalDeclEraser(std::set<const clang::Decl *> &decls, - const clang::Decl *decl) - : m_active_lexical_decls(decls), m_decl(decl) - { - } +class ScopedLexicalDeclEraser { +public: + ScopedLexicalDeclEraser(std::set<const clang::Decl *> &decls, + const clang::Decl *decl) + : m_active_lexical_decls(decls), m_decl(decl) {} - ~ScopedLexicalDeclEraser() - { - m_active_lexical_decls.erase(m_decl); - } + ~ScopedLexicalDeclEraser() { m_active_lexical_decls.erase(m_decl); } - private: - std::set<const clang::Decl *> &m_active_lexical_decls; - const clang::Decl *m_decl; - }; +private: + std::set<const clang::Decl *> &m_active_lexical_decls; + const clang::Decl *m_decl; +}; } -ClangASTSource::~ClangASTSource() -{ - m_ast_importer_sp->ForgetDestination(m_ast_context); +ClangASTSource::~ClangASTSource() { + m_ast_importer_sp->ForgetDestination(m_ast_context); - // We are in the process of destruction, don't create clang ast context on demand - // by passing false to Target::GetScratchClangASTContext(create_on_demand). - ClangASTContext *scratch_clang_ast_context = m_target->GetScratchClangASTContext(false); + // We are in the process of destruction, don't create clang ast context on + // demand + // by passing false to Target::GetScratchClangASTContext(create_on_demand). + ClangASTContext *scratch_clang_ast_context = + m_target->GetScratchClangASTContext(false); - if (!scratch_clang_ast_context) - return; + if (!scratch_clang_ast_context) + return; - clang::ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext(); + clang::ASTContext *scratch_ast_context = + scratch_clang_ast_context->getASTContext(); - if (!scratch_ast_context) - return; + if (!scratch_ast_context) + return; - if (m_ast_context != scratch_ast_context) - m_ast_importer_sp->ForgetSource(scratch_ast_context, m_ast_context); + if (m_ast_context != scratch_ast_context) + m_ast_importer_sp->ForgetSource(scratch_ast_context, m_ast_context); } -void -ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) -{ - if (!m_ast_context) - return; +void ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) { + if (!m_ast_context) + return; - m_ast_context->getTranslationUnitDecl()->setHasExternalVisibleStorage(); - m_ast_context->getTranslationUnitDecl()->setHasExternalLexicalStorage(); + m_ast_context->getTranslationUnitDecl()->setHasExternalVisibleStorage(); + m_ast_context->getTranslationUnitDecl()->setHasExternalLexicalStorage(); } // The core lookup interface. -bool -ClangASTSource::FindExternalVisibleDeclsByName -( - const DeclContext *decl_ctx, - DeclarationName clang_decl_name -) -{ - if (!m_ast_context) - { - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; +bool ClangASTSource::FindExternalVisibleDeclsByName( + const DeclContext *decl_ctx, DeclarationName clang_decl_name) { + if (!m_ast_context) { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + + if (GetImportInProgress()) { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + + std::string decl_name(clang_decl_name.getAsString()); + + // if (m_decl_map.DoingASTImport ()) + // return DeclContext::lookup_result(); + // + switch (clang_decl_name.getNameKind()) { + // Normal identifiers. + case DeclarationName::Identifier: { + clang::IdentifierInfo *identifier_info = + clang_decl_name.getAsIdentifierInfo(); + + if (!identifier_info || identifier_info->getBuiltinID() != 0) { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; } - - if (GetImportInProgress()) - { - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; + } break; + + // Operator names. + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: + break; + + // Using directives found in this context. + // Tell Sema we didn't find any or we'll end up getting asked a *lot*. + case DeclarationName::CXXUsingDirective: + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: { + llvm::SmallVector<NamedDecl *, 1> method_decls; + + NameSearchContext method_search_context(*this, method_decls, + clang_decl_name, decl_ctx); + + FindObjCMethodDecls(method_search_context); + + SetExternalVisibleDeclsForName(decl_ctx, clang_decl_name, method_decls); + return (method_decls.size() > 0); + } + // These aren't possible in the global context. + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + + if (!GetLookupsEnabled()) { + // Wait until we see a '$' at the start of a name before we start doing + // any lookups so we can avoid lookup up all of the builtin types. + if (!decl_name.empty() && decl_name[0] == '$') { + SetLookupsEnabled(true); + } else { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; } + } + + ConstString const_decl_name(decl_name.c_str()); + + const char *uniqued_const_decl_name = const_decl_name.GetCString(); + if (m_active_lookups.find(uniqued_const_decl_name) != + m_active_lookups.end()) { + // We are currently looking up this name... + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + m_active_lookups.insert(uniqued_const_decl_name); + // static uint32_t g_depth = 0; + // ++g_depth; + // printf("[%5u] FindExternalVisibleDeclsByName() \"%s\"\n", g_depth, + // uniqued_const_decl_name); + llvm::SmallVector<NamedDecl *, 4> name_decls; + NameSearchContext name_search_context(*this, name_decls, clang_decl_name, + decl_ctx); + FindExternalVisibleDecls(name_search_context); + SetExternalVisibleDeclsForName(decl_ctx, clang_decl_name, name_decls); + // --g_depth; + m_active_lookups.erase(uniqued_const_decl_name); + return (name_decls.size() != 0); +} - std::string decl_name (clang_decl_name.getAsString()); +void ClangASTSource::CompleteType(TagDecl *tag_decl) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); -// if (m_decl_map.DoingASTImport ()) -// return DeclContext::lookup_result(); -// - switch (clang_decl_name.getNameKind()) { - // Normal identifiers. - case DeclarationName::Identifier: - { - clang::IdentifierInfo *identifier_info = clang_decl_name.getAsIdentifierInfo(); - - if (!identifier_info || - identifier_info->getBuiltinID() != 0) - { - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - } - } - break; + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; - // Operator names. - case DeclarationName::CXXOperatorName: - case DeclarationName::CXXLiteralOperatorName: - break; + if (log) { + log->Printf(" CompleteTagDecl[%u] on (ASTContext*)%p Completing " + "(TagDecl*)%p named %s", + current_id, static_cast<void *>(m_ast_context), + static_cast<void *>(tag_decl), + tag_decl->getName().str().c_str()); - // Using directives found in this context. - // Tell Sema we didn't find any or we'll end up getting asked a *lot*. - case DeclarationName::CXXUsingDirective: - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; + log->Printf(" CTD[%u] Before:", current_id); + ASTDumper dumper((Decl *)tag_decl); + dumper.ToLog(log, " [CTD] "); + } - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - { - llvm::SmallVector<NamedDecl*, 1> method_decls; + auto iter = m_active_lexical_decls.find(tag_decl); + if (iter != m_active_lexical_decls.end()) + return; + m_active_lexical_decls.insert(tag_decl); + ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl); - NameSearchContext method_search_context (*this, method_decls, clang_decl_name, decl_ctx); + if (!m_ast_importer_sp->CompleteTagDecl(tag_decl)) { + // We couldn't complete the type. Maybe there's a definition + // somewhere else that can be completed. - FindObjCMethodDecls(method_search_context); + if (log) + log->Printf(" CTD[%u] Type could not be completed in the module in " + "which it was first found.", + current_id); - SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, method_decls); - return (method_decls.size() > 0); - } - // These aren't possible in the global context. - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - } + bool found = false; + DeclContext *decl_ctx = tag_decl->getDeclContext(); - if (!GetLookupsEnabled()) - { - // Wait until we see a '$' at the start of a name before we start doing - // any lookups so we can avoid lookup up all of the builtin types. - if (!decl_name.empty() && decl_name[0] == '$') - { - SetLookupsEnabled (true); - } - else - { - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - } - } + if (const NamespaceDecl *namespace_context = + dyn_cast<NamespaceDecl>(decl_ctx)) { + ClangASTImporter::NamespaceMapSP namespace_map = + m_ast_importer_sp->GetNamespaceMap(namespace_context); - ConstString const_decl_name(decl_name.c_str()); + if (log && log->GetVerbose()) + log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)", + current_id, static_cast<void *>(namespace_map.get()), + static_cast<int>(namespace_map->size())); - const char *uniqued_const_decl_name = const_decl_name.GetCString(); - if (m_active_lookups.find (uniqued_const_decl_name) != m_active_lookups.end()) - { - // We are currently looking up this name... - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - } - m_active_lookups.insert(uniqued_const_decl_name); -// static uint32_t g_depth = 0; -// ++g_depth; -// printf("[%5u] FindExternalVisibleDeclsByName() \"%s\"\n", g_depth, uniqued_const_decl_name); - llvm::SmallVector<NamedDecl*, 4> name_decls; - NameSearchContext name_search_context(*this, name_decls, clang_decl_name, decl_ctx); - FindExternalVisibleDecls(name_search_context); - SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, name_decls); -// --g_depth; - m_active_lookups.erase (uniqued_const_decl_name); - return (name_decls.size() != 0); -} + if (!namespace_map) + return; -void -ClangASTSource::CompleteType (TagDecl *tag_decl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), + e = namespace_map->end(); + i != e && !found; ++i) { + if (log) + log->Printf(" CTD[%u] Searching namespace %s in module %s", + current_id, i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; + TypeList types; - if (log) - { - log->Printf(" CompleteTagDecl[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s", - current_id, static_cast<void*>(m_ast_context), - static_cast<void*>(tag_decl), - tag_decl->getName().str().c_str()); - - log->Printf(" CTD[%u] Before:", current_id); - ASTDumper dumper((Decl*)tag_decl); - dumper.ToLog(log, " [CTD] "); - } + SymbolContext null_sc; + ConstString name(tag_decl->getName().str().c_str()); - auto iter = m_active_lexical_decls.find(tag_decl); - if (iter != m_active_lexical_decls.end()) - return; - m_active_lexical_decls.insert(tag_decl); - ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl); + i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, + types); - if (!m_ast_importer_sp->CompleteTagDecl (tag_decl)) - { - // We couldn't complete the type. Maybe there's a definition - // somewhere else that can be completed. + for (uint32_t ti = 0, te = types.GetSize(); ti != te && !found; ++ti) { + lldb::TypeSP type = types.GetTypeAtIndex(ti); - if (log) - log->Printf(" CTD[%u] Type could not be completed in the module in which it was first found.", current_id); + if (!type) + continue; - bool found = false; + CompilerType clang_type(type->GetFullCompilerType()); - DeclContext *decl_ctx = tag_decl->getDeclContext(); + if (!ClangUtil::IsClangType(clang_type)) + continue; - if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(decl_ctx)) - { - ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); + const TagType *tag_type = + ClangUtil::GetQualType(clang_type)->getAs<TagType>(); - if (log && log->GetVerbose()) - log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)", - current_id, static_cast<void*>(namespace_map.get()), - static_cast<int>(namespace_map->size())); + if (!tag_type) + continue; - if (!namespace_map) - return; + TagDecl *candidate_tag_decl = + const_cast<TagDecl *>(tag_type->getDecl()); - for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); - i != e && !found; - ++i) - { - if (log) - log->Printf(" CTD[%u] Searching namespace %s in module %s", - current_id, - i->second.GetName().AsCString(), - i->first->GetFileSpec().GetFilename().GetCString()); + if (m_ast_importer_sp->CompleteTagDeclWithOrigin(tag_decl, + candidate_tag_decl)) + found = true; + } + } + } else { + TypeList types; - TypeList types; + SymbolContext null_sc; + ConstString name(tag_decl->getName().str().c_str()); + CompilerDeclContext namespace_decl; - SymbolContext null_sc; - ConstString name(tag_decl->getName().str().c_str()); + const ModuleList &module_list = m_target->GetImages(); - i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, types); + bool exact_match = false; + llvm::DenseSet<SymbolFile *> searched_symbol_files; + module_list.FindTypes(null_sc, name, exact_match, UINT32_MAX, + searched_symbol_files, types); - for (uint32_t ti = 0, te = types.GetSize(); - ti != te && !found; - ++ti) - { - lldb::TypeSP type = types.GetTypeAtIndex(ti); + for (uint32_t ti = 0, te = types.GetSize(); ti != te && !found; ++ti) { + lldb::TypeSP type = types.GetTypeAtIndex(ti); - if (!type) - continue; + if (!type) + continue; - CompilerType clang_type (type->GetFullCompilerType ()); + CompilerType clang_type(type->GetFullCompilerType()); - if (!ClangUtil::IsClangType(clang_type)) - continue; + if (!ClangUtil::IsClangType(clang_type)) + continue; - const TagType *tag_type = ClangUtil::GetQualType(clang_type)->getAs<TagType>(); + const TagType *tag_type = + ClangUtil::GetQualType(clang_type)->getAs<TagType>(); - if (!tag_type) - continue; + if (!tag_type) + continue; - TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl()); + TagDecl *candidate_tag_decl = + const_cast<TagDecl *>(tag_type->getDecl()); - if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl)) - found = true; - } - } - } - else - { - TypeList types; + // We have found a type by basename and we need to make sure the decl + // contexts + // are the same before we can try to complete this type with another + if (!ClangASTContext::DeclsAreEquivalent(tag_decl, candidate_tag_decl)) + continue; - SymbolContext null_sc; - ConstString name(tag_decl->getName().str().c_str()); - CompilerDeclContext namespace_decl; + if (m_ast_importer_sp->CompleteTagDeclWithOrigin(tag_decl, + candidate_tag_decl)) + found = true; + } + } + } - const ModuleList &module_list = m_target->GetImages(); + if (log) { + log->Printf(" [CTD] After:"); + ASTDumper dumper((Decl *)tag_decl); + dumper.ToLog(log, " [CTD] "); + } +} - bool exact_match = false; - llvm::DenseSet<SymbolFile *> searched_symbol_files; - module_list.FindTypes (null_sc, name, exact_match, UINT32_MAX, searched_symbol_files, types); +void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) { + log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing " + "an ObjCInterfaceDecl named %s", + static_cast<void *>(m_ast_context), + interface_decl->getName().str().c_str()); + log->Printf(" [COID] Before:"); + ASTDumper dumper((Decl *)interface_decl); + dumper.ToLog(log, " [COID] "); + } + + Decl *original_decl = NULL; + ASTContext *original_ctx = NULL; + + if (m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, + &original_ctx)) { + if (ObjCInterfaceDecl *original_iface_decl = + dyn_cast<ObjCInterfaceDecl>(original_decl)) { + ObjCInterfaceDecl *complete_iface_decl = + GetCompleteObjCInterface(original_iface_decl); + + if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) { + m_ast_importer_sp->SetDeclOrigin(interface_decl, original_iface_decl); + } + } + } - for (uint32_t ti = 0, te = types.GetSize(); - ti != te && !found; - ++ti) - { - lldb::TypeSP type = types.GetTypeAtIndex(ti); + m_ast_importer_sp->CompleteObjCInterfaceDecl(interface_decl); - if (!type) - continue; + if (interface_decl->getSuperClass() && + interface_decl->getSuperClass() != interface_decl) + CompleteType(interface_decl->getSuperClass()); - CompilerType clang_type (type->GetFullCompilerType ()); + if (log) { + log->Printf(" [COID] After:"); + ASTDumper dumper((Decl *)interface_decl); + dumper.ToLog(log, " [COID] "); + } +} - if (!ClangUtil::IsClangType(clang_type)) - continue; +clang::ObjCInterfaceDecl *ClangASTSource::GetCompleteObjCInterface( + clang::ObjCInterfaceDecl *interface_decl) { + lldb::ProcessSP process(m_target->GetProcessSP()); - const TagType *tag_type = ClangUtil::GetQualType(clang_type)->getAs<TagType>(); + if (!process) + return NULL; - if (!tag_type) - continue; + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); - TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl()); + if (!language_runtime) + return NULL; - // We have found a type by basename and we need to make sure the decl contexts - // are the same before we can try to complete this type with another - if (!ClangASTContext::DeclsAreEquivalent (tag_decl, candidate_tag_decl)) - continue; + ConstString class_name(interface_decl->getNameAsString().c_str()); - if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl)) - found = true; - } - } - } + lldb::TypeSP complete_type_sp( + language_runtime->LookupInCompleteClassCache(class_name)); - if (log) - { - log->Printf(" [CTD] After:"); - ASTDumper dumper((Decl*)tag_decl); - dumper.ToLog(log, " [CTD] "); - } -} + if (!complete_type_sp) + return NULL; -void -ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + TypeFromUser complete_type = + TypeFromUser(complete_type_sp->GetFullCompilerType()); + lldb::opaque_compiler_type_t complete_opaque_type = + complete_type.GetOpaqueQualType(); - if (log) - { - log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing an ObjCInterfaceDecl named %s", - static_cast<void*>(m_ast_context), - interface_decl->getName().str().c_str()); - log->Printf(" [COID] Before:"); - ASTDumper dumper((Decl*)interface_decl); - dumper.ToLog(log, " [COID] "); - } + if (!complete_opaque_type) + return NULL; - Decl *original_decl = NULL; - ASTContext *original_ctx = NULL; + const clang::Type *complete_clang_type = + QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr(); + const ObjCInterfaceType *complete_interface_type = + dyn_cast<ObjCInterfaceType>(complete_clang_type); - if (m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx)) - { - if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl)) - { - ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); + if (!complete_interface_type) + return NULL; - if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) - { - m_ast_importer_sp->SetDeclOrigin(interface_decl, original_iface_decl); - } - } - } + ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl()); - m_ast_importer_sp->CompleteObjCInterfaceDecl (interface_decl); + return complete_iface_decl; +} - if (interface_decl->getSuperClass() && - interface_decl->getSuperClass() != interface_decl) - CompleteType(interface_decl->getSuperClass()); +void ClangASTSource::FindExternalLexicalDecls( + const DeclContext *decl_context, + llvm::function_ref<bool(Decl::Kind)> predicate, + llvm::SmallVectorImpl<Decl *> &decls) { + ClangASTMetrics::RegisterLexicalQuery(); - if (log) - { - log->Printf(" [COID] After:"); - ASTDumper dumper((Decl*)interface_decl); - dumper.ToLog(log, " [COID] "); - } -} + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); -clang::ObjCInterfaceDecl * -ClangASTSource::GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl) -{ - lldb::ProcessSP process(m_target->GetProcessSP()); + const Decl *context_decl = dyn_cast<Decl>(decl_context); - if (!process) - return NULL; + if (!context_decl) + return; - ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + auto iter = m_active_lexical_decls.find(context_decl); + if (iter != m_active_lexical_decls.end()) + return; + m_active_lexical_decls.insert(context_decl); + ScopedLexicalDeclEraser eraser(m_active_lexical_decls, context_decl); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + if (log) { + if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl)) + log->Printf( + "FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p", + current_id, static_cast<void *>(m_ast_context), + context_named_decl->getNameAsString().c_str(), + context_decl->getDeclKindName(), + static_cast<const void *>(context_decl)); + else if (context_decl) + log->Printf( + "FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p", + current_id, static_cast<void *>(m_ast_context), + context_decl->getDeclKindName(), + static_cast<const void *>(context_decl)); + else + log->Printf( + "FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context", + current_id, static_cast<const void *>(m_ast_context)); + } - if (!language_runtime) - return NULL; + Decl *original_decl = NULL; + ASTContext *original_ctx = NULL; - ConstString class_name(interface_decl->getNameAsString().c_str()); + if (!m_ast_importer_sp->ResolveDeclOrigin(context_decl, &original_decl, + &original_ctx)) + return; - lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name)); + if (log) { + log->Printf(" FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", + current_id, static_cast<void *>(original_ctx), + static_cast<void *>(original_decl)); + ASTDumper(original_decl).ToLog(log, " "); + } - if (!complete_type_sp) - return NULL; + if (ObjCInterfaceDecl *original_iface_decl = + dyn_cast<ObjCInterfaceDecl>(original_decl)) { + ObjCInterfaceDecl *complete_iface_decl = + GetCompleteObjCInterface(original_iface_decl); - TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetFullCompilerType ()); - lldb::opaque_compiler_type_t complete_opaque_type = complete_type.GetOpaqueQualType(); + if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) { + original_decl = complete_iface_decl; + original_ctx = &complete_iface_decl->getASTContext(); - if (!complete_opaque_type) - return NULL; + m_ast_importer_sp->SetDeclOrigin(context_decl, original_iface_decl); + } + } - const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr(); - const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type); + if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl)) { + ExternalASTSource *external_source = original_ctx->getExternalSource(); - if (!complete_interface_type) - return NULL; + if (external_source) + external_source->CompleteType(original_tag_decl); + } - ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl()); + const DeclContext *original_decl_context = + dyn_cast<DeclContext>(original_decl); - return complete_iface_decl; -} + if (!original_decl_context) + return; + + for (TagDecl::decl_iterator iter = original_decl_context->decls_begin(); + iter != original_decl_context->decls_end(); ++iter) { + Decl *decl = *iter; + + if (predicate(decl->getKind())) { + if (log) { + ASTDumper ast_dumper(decl); + if (const NamedDecl *context_named_decl = + dyn_cast<NamedDecl>(context_decl)) + log->Printf(" FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", + current_id, context_named_decl->getDeclKindName(), + context_named_decl->getNameAsString().c_str(), + decl->getDeclKindName(), ast_dumper.GetCString()); + else + log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, + decl->getDeclKindName(), ast_dumper.GetCString()); + } -void -ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context, - llvm::function_ref<bool(Decl::Kind)> predicate, - llvm::SmallVectorImpl<Decl*> &decls) -{ - ClangASTMetrics::RegisterLexicalQuery(); + Decl *copied_decl = + m_ast_importer_sp->CopyDecl(m_ast_context, original_ctx, decl); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (!copied_decl) + continue; - const Decl *context_decl = dyn_cast<Decl>(decl_context); + if (FieldDecl *copied_field = dyn_cast<FieldDecl>(copied_decl)) { + QualType copied_field_type = copied_field->getType(); - if (!context_decl) - return; + m_ast_importer_sp->RequireCompleteType(copied_field_type); + } - auto iter = m_active_lexical_decls.find(context_decl); - if (iter != m_active_lexical_decls.end()) - return; - m_active_lexical_decls.insert(context_decl); - ScopedLexicalDeclEraser eraser(m_active_lexical_decls, context_decl); + DeclContext *decl_context_non_const = + const_cast<DeclContext *>(decl_context); - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; + if (copied_decl->getDeclContext() != decl_context) { + if (copied_decl->getDeclContext()->containsDecl(copied_decl)) + copied_decl->getDeclContext()->removeDecl(copied_decl); + copied_decl->setDeclContext(decl_context_non_const); + } - if (log) - { - if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl)) - log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p", - current_id, static_cast<void*>(m_ast_context), - context_named_decl->getNameAsString().c_str(), - context_decl->getDeclKindName(), - static_cast<const void*>(context_decl)); - else if(context_decl) - log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p", - current_id, static_cast<void*>(m_ast_context), - context_decl->getDeclKindName(), - static_cast<const void*>(context_decl)); - else - log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context", - current_id, static_cast<const void*>(m_ast_context)); + if (!decl_context_non_const->containsDecl(copied_decl)) + decl_context_non_const->addDeclInternal(copied_decl); } + } - Decl *original_decl = NULL; - ASTContext *original_ctx = NULL; + return; +} - if (!m_ast_importer_sp->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx)) - return; +void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { + assert(m_ast_context); - if (log) - { - log->Printf(" FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", - current_id, static_cast<void*>(original_ctx), - static_cast<void*>(original_decl)); - ASTDumper(original_decl).ToLog(log, " "); - } + ClangASTMetrics::RegisterVisibleQuery(); - if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl)) - { - ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); + const ConstString name(context.m_decl_name.getAsString().c_str()); - if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) - { - original_decl = complete_iface_decl; - original_ctx = &complete_iface_decl->getASTContext(); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - m_ast_importer_sp->SetDeclOrigin(context_decl, original_iface_decl); - } + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + if (log) { + if (!context.m_decl_context) + log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on " + "(ASTContext*)%p for '%s' in a NULL DeclContext", + current_id, static_cast<void *>(m_ast_context), + name.GetCString()); + else if (const NamedDecl *context_named_decl = + dyn_cast<NamedDecl>(context.m_decl_context)) + log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on " + "(ASTContext*)%p for '%s' in '%s'", + current_id, static_cast<void *>(m_ast_context), + name.GetCString(), + context_named_decl->getNameAsString().c_str()); + else + log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on " + "(ASTContext*)%p for '%s' in a '%s'", + current_id, static_cast<void *>(m_ast_context), + name.GetCString(), context.m_decl_context->getDeclKindName()); + } + + context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap); + + if (const NamespaceDecl *namespace_context = + dyn_cast<NamespaceDecl>(context.m_decl_context)) { + ClangASTImporter::NamespaceMapSP namespace_map = + m_ast_importer_sp->GetNamespaceMap(namespace_context); + + if (log && log->GetVerbose()) + log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", + current_id, static_cast<void *>(namespace_map.get()), + static_cast<int>(namespace_map->size())); + + if (!namespace_map) + return; + + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), + e = namespace_map->end(); + i != e; ++i) { + if (log) + log->Printf(" CAS::FEVD[%u] Searching namespace %s in module %s", + current_id, i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); + + FindExternalVisibleDecls(context, i->first, i->second, current_id); } + } else if (isa<ObjCInterfaceDecl>(context.m_decl_context)) { + FindObjCPropertyAndIvarDecls(context); + } else if (!isa<TranslationUnitDecl>(context.m_decl_context)) { + // we shouldn't be getting FindExternalVisibleDecls calls for these + return; + } else { + CompilerDeclContext namespace_decl; - if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl)) - { - ExternalASTSource *external_source = original_ctx->getExternalSource(); + if (log) + log->Printf(" CAS::FEVD[%u] Searching the root namespace", current_id); - if (external_source) - external_source->CompleteType (original_tag_decl); - } + FindExternalVisibleDecls(context, lldb::ModuleSP(), namespace_decl, + current_id); + } - const DeclContext *original_decl_context = dyn_cast<DeclContext>(original_decl); + if (!context.m_namespace_map->empty()) { + if (log && log->GetVerbose()) + log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)", + current_id, + static_cast<void *>(context.m_namespace_map.get()), + static_cast<int>(context.m_namespace_map->size())); - if (!original_decl_context) - return; + NamespaceDecl *clang_namespace_decl = + AddNamespace(context, context.m_namespace_map); - for (TagDecl::decl_iterator iter = original_decl_context->decls_begin(); - iter != original_decl_context->decls_end(); - ++iter) - { - Decl *decl = *iter; - - if (predicate(decl->getKind())) - { - if (log) - { - ASTDumper ast_dumper(decl); - if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl)) - log->Printf(" FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", current_id, context_named_decl->getDeclKindName(), context_named_decl->getNameAsString().c_str(), decl->getDeclKindName(), ast_dumper.GetCString()); - else - log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString()); - } - - Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, original_ctx, decl); + if (clang_namespace_decl) + clang_namespace_decl->setHasExternalVisibleStorage(); + } +} - if (!copied_decl) - continue; +void ClangASTSource::FindExternalVisibleDecls( + NameSearchContext &context, lldb::ModuleSP module_sp, + CompilerDeclContext &namespace_decl, unsigned int current_id) { + assert(m_ast_context); - if (FieldDecl *copied_field = dyn_cast<FieldDecl>(copied_decl)) - { - QualType copied_field_type = copied_field->getType(); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - m_ast_importer_sp->RequireCompleteType(copied_field_type); - } + SymbolContextList sc_list; - DeclContext *decl_context_non_const = const_cast<DeclContext *>(decl_context); + const ConstString name(context.m_decl_name.getAsString().c_str()); - if (copied_decl->getDeclContext() != decl_context) - { - if (copied_decl->getDeclContext()->containsDecl(copied_decl)) - copied_decl->getDeclContext()->removeDecl(copied_decl); - copied_decl->setDeclContext(decl_context_non_const); - } + const char *name_unique_cstr = name.GetCString(); - if (!decl_context_non_const->containsDecl(copied_decl)) - decl_context_non_const->addDeclInternal(copied_decl); - } - } + static ConstString id_name("id"); + static ConstString Class_name("Class"); + if (name == id_name || name == Class_name) return; -} -void -ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context) -{ - assert (m_ast_context); + if (name_unique_cstr == NULL) + return; - ClangASTMetrics::RegisterVisibleQuery(); + // The ClangASTSource is not responsible for finding $-names. + if (name_unique_cstr[0] == '$') + return; - const ConstString name(context.m_decl_name.getAsString().c_str()); + if (module_sp && namespace_decl) { + CompilerDeclContext found_namespace_decl; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; + if (symbol_vendor) { + SymbolContext null_sc; - if (log) - { - if (!context.m_decl_context) - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a NULL DeclContext", - current_id, static_cast<void*>(m_ast_context), - name.GetCString()); - else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context)) - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in '%s'", - current_id, static_cast<void*>(m_ast_context), - name.GetCString(), - context_named_decl->getNameAsString().c_str()); - else - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a '%s'", - current_id, static_cast<void*>(m_ast_context), - name.GetCString(), - context.m_decl_context->getDeclKindName()); - } + found_namespace_decl = + symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); - context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap); - - if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context)) - { - ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); - - if (log && log->GetVerbose()) - log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", - current_id, static_cast<void*>(namespace_map.get()), - static_cast<int>(namespace_map->size())); - - if (!namespace_map) - return; - - for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); - i != e; - ++i) - { - if (log) - log->Printf(" CAS::FEVD[%u] Searching namespace %s in module %s", - current_id, - i->second.GetName().AsCString(), - i->first->GetFileSpec().GetFilename().GetCString()); - - FindExternalVisibleDecls(context, - i->first, - i->second, - current_id); - } - } - else if (isa<ObjCInterfaceDecl>(context.m_decl_context)) - { - FindObjCPropertyAndIvarDecls(context); - } - else if (!isa<TranslationUnitDecl>(context.m_decl_context)) - { - // we shouldn't be getting FindExternalVisibleDecls calls for these - return; - } - else - { - CompilerDeclContext namespace_decl; + if (found_namespace_decl) { + context.m_namespace_map->push_back( + std::pair<lldb::ModuleSP, CompilerDeclContext>( + module_sp, found_namespace_decl)); if (log) - log->Printf(" CAS::FEVD[%u] Searching the root namespace", current_id); - - FindExternalVisibleDecls(context, - lldb::ModuleSP(), - namespace_decl, - current_id); + log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", + current_id, name.GetCString(), + module_sp->GetFileSpec().GetFilename().GetCString()); + } } + } else { + const ModuleList &target_images = m_target->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); + + for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) { + lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); + + if (!image) + continue; + + CompilerDeclContext found_namespace_decl; - if (!context.m_namespace_map->empty()) - { - if (log && log->GetVerbose()) - log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)", - current_id, - static_cast<void*>(context.m_namespace_map.get()), - static_cast<int>(context.m_namespace_map->size())); + SymbolVendor *symbol_vendor = image->GetSymbolVendor(); - NamespaceDecl *clang_namespace_decl = AddNamespace(context, context.m_namespace_map); + if (!symbol_vendor) + continue; - if (clang_namespace_decl) - clang_namespace_decl->setHasExternalVisibleStorage(); + SymbolContext null_sc; + + found_namespace_decl = + symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); + + if (found_namespace_decl) { + context.m_namespace_map->push_back( + std::pair<lldb::ModuleSP, CompilerDeclContext>( + image, found_namespace_decl)); + + if (log) + log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", + current_id, name.GetCString(), + image->GetFileSpec().GetFilename().GetCString()); + } } -} + } -void -ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, - lldb::ModuleSP module_sp, - CompilerDeclContext &namespace_decl, - unsigned int current_id) -{ - assert (m_ast_context); + do { + if (context.m_found.type) + break; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + TypeList types; + SymbolContext null_sc; + const bool exact_match = false; + llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; + if (module_sp && namespace_decl) + module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types); + else + m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, + searched_symbol_files, types); - SymbolContextList sc_list; + if (size_t num_types = types.GetSize()) { + for (size_t ti = 0; ti < num_types; ++ti) { + lldb::TypeSP type_sp = types.GetTypeAtIndex(ti); - const ConstString name(context.m_decl_name.getAsString().c_str()); + if (log) { + const char *name_string = type_sp->GetName().GetCString(); - const char *name_unique_cstr = name.GetCString(); + log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s", + current_id, name.GetCString(), + (name_string ? name_string : "<anonymous>")); + } - static ConstString id_name("id"); - static ConstString Class_name("Class"); + CompilerType full_type = type_sp->GetFullCompilerType(); - if (name == id_name || name == Class_name) - return; + CompilerType copied_clang_type(GuardedCopyType(full_type)); - if (name_unique_cstr == NULL) - return; + if (!copied_clang_type) { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a type", current_id); - // The ClangASTSource is not responsible for finding $-names. - if (name_unique_cstr[0] == '$') - return; + continue; + } - if (module_sp && namespace_decl) - { - CompilerDeclContext found_namespace_decl; + context.AddTypeDecl(copied_clang_type); - SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); + context.m_found.type = true; + break; + } + } - if (symbol_vendor) - { - SymbolContext null_sc; + if (!context.m_found.type) { + // Try the modules next. - found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); + do { + if (ClangModulesDeclVendor *modules_decl_vendor = + m_target->GetClangModulesDeclVendor()) { + bool append = false; + uint32_t max_matches = 1; + std::vector<clang::NamedDecl *> decls; - if (found_namespace_decl) - { - context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(module_sp, found_namespace_decl)); + if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls)) + break; - if (log) - log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", - current_id, - name.GetCString(), - module_sp->GetFileSpec().GetFilename().GetCString()); + if (log) { + log->Printf(" CAS::FEVD[%u] Matching entity found for \"%s\" in " + "the modules", + current_id, name.GetCString()); + } + + clang::NamedDecl *const decl_from_modules = decls[0]; + + if (llvm::isa<clang::TypeDecl>(decl_from_modules) || + llvm::isa<clang::ObjCContainerDecl>(decl_from_modules) || + llvm::isa<clang::EnumConstantDecl>(decl_from_modules)) { + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( + m_ast_context, &decl_from_modules->getASTContext(), + decl_from_modules); + clang::NamedDecl *copied_named_decl = + copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; + + if (!copied_named_decl) { + if (log) + log->Printf( + " CAS::FEVD[%u] - Couldn't export a type from the modules", + current_id); + + break; } + + context.AddNamedDecl(copied_named_decl); + + context.m_found.type = true; + } } + } while (0); } - else - { - const ModuleList &target_images = m_target->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); - for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) - { - lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); + if (!context.m_found.type) { + do { + // Couldn't find any types elsewhere. Try the Objective-C runtime if + // one exists. - if (!image) - continue; + lldb::ProcessSP process(m_target->GetProcessSP()); - CompilerDeclContext found_namespace_decl; + if (!process) + break; - SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + ObjCLanguageRuntime *language_runtime( + process->GetObjCLanguageRuntime()); - if (!symbol_vendor) - continue; + if (!language_runtime) + break; - SymbolContext null_sc; + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); - found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); + if (!decl_vendor) + break; - if (found_namespace_decl) - { - context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(image, found_namespace_decl)); + bool append = false; + uint32_t max_matches = 1; + std::vector<clang::NamedDecl *> decls; - if (log) - log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", - current_id, - name.GetCString(), - image->GetFileSpec().GetFilename().GetCString()); - } - } - } + if (!decl_vendor->FindDecls(name, append, max_matches, decls)) + break; - do - { - if (context.m_found.type) - break; - - TypeList types; - SymbolContext null_sc; - const bool exact_match = false; - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - if (module_sp && namespace_decl) - module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types); - else - m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, searched_symbol_files, types); - - if (size_t num_types = types.GetSize()) - { - for (size_t ti = 0; ti < num_types; ++ti) - { - lldb::TypeSP type_sp = types.GetTypeAtIndex(ti); - - if (log) - { - const char *name_string = type_sp->GetName().GetCString(); - - log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s", - current_id, - name.GetCString(), - (name_string ? name_string : "<anonymous>")); - } - - CompilerType full_type = type_sp->GetFullCompilerType(); - - CompilerType copied_clang_type (GuardedCopyType(full_type)); - - if (!copied_clang_type) - { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a type", - current_id); - - continue; - } - - context.AddTypeDecl(copied_clang_type); - - context.m_found.type = true; - break; - } + if (log) { + log->Printf( + " CAS::FEVD[%u] Matching type found for \"%s\" in the runtime", + current_id, name.GetCString()); } - if (!context.m_found.type) - { - // Try the modules next. - - do - { - if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) - { - bool append = false; - uint32_t max_matches = 1; - std::vector <clang::NamedDecl *> decls; - - if (!modules_decl_vendor->FindDecls(name, - append, - max_matches, - decls)) - break; - - if (log) - { - log->Printf(" CAS::FEVD[%u] Matching entity found for \"%s\" in the modules", - current_id, - name.GetCString()); - } - - clang::NamedDecl *const decl_from_modules = decls[0]; - - if (llvm::isa<clang::TypeDecl>(decl_from_modules) || - llvm::isa<clang::ObjCContainerDecl>(decl_from_modules) || - llvm::isa<clang::EnumConstantDecl>(decl_from_modules)) - { - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); - clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; - - if (!copied_named_decl) - { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the modules", - current_id); - - break; - } - - context.AddNamedDecl(copied_named_decl); - - context.m_found.type = true; - } - } - } while (0); - } - - if (!context.m_found.type) - { - do - { - // Couldn't find any types elsewhere. Try the Objective-C runtime if one exists. - - lldb::ProcessSP process(m_target->GetProcessSP()); - - if (!process) - break; - - ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); - - if (!language_runtime) - break; - - DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); - - if (!decl_vendor) - break; - - bool append = false; - uint32_t max_matches = 1; - std::vector <clang::NamedDecl *> decls; - - if (!decl_vendor->FindDecls(name, - append, - max_matches, - decls)) - break; - - if (log) - { - log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\" in the runtime", - current_id, - name.GetCString()); - } - - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decls[0]->getASTContext(), decls[0]); - clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; - - if (!copied_named_decl) - { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the runtime", - current_id); - - break; - } - - context.AddNamedDecl(copied_named_decl); - } - while(0); + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( + m_ast_context, &decls[0]->getASTContext(), decls[0]); + clang::NamedDecl *copied_named_decl = + copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; + + if (!copied_named_decl) { + if (log) + log->Printf( + " CAS::FEVD[%u] - Couldn't export a type from the runtime", + current_id); + + break; } - } while(0); + context.AddNamedDecl(copied_named_decl); + } while (0); + } + + } while (0); } template <class D> class TaggedASTDecl { public: - TaggedASTDecl() : decl(NULL) { } - TaggedASTDecl(D *_decl) : decl(_decl) { } - bool IsValid() const { return (decl != NULL); } - bool IsInvalid() const { return !IsValid(); } - D *operator->() const { return decl; } - D *decl; + TaggedASTDecl() : decl(NULL) {} + TaggedASTDecl(D *_decl) : decl(_decl) {} + bool IsValid() const { return (decl != NULL); } + bool IsInvalid() const { return !IsValid(); } + D *operator->() const { return decl; } + D *decl; }; template <class D2, template <class D> class TD, class D1> -TD<D2> -DynCast(TD<D1> source) -{ - return TD<D2> (dyn_cast<D2>(source.decl)); +TD<D2> DynCast(TD<D1> source) { + return TD<D2>(dyn_cast<D2>(source.decl)); } template <class D = Decl> class DeclFromParser; @@ -922,1179 +872,1141 @@ template <class D = Decl> class DeclFromUser; template <class D> class DeclFromParser : public TaggedASTDecl<D> { public: - DeclFromParser() : TaggedASTDecl<D>() { } - DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) { } + DeclFromParser() : TaggedASTDecl<D>() {} + DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) {} - DeclFromUser<D> GetOrigin(ClangASTImporter *importer); + DeclFromUser<D> GetOrigin(ClangASTImporter *importer); }; template <class D> class DeclFromUser : public TaggedASTDecl<D> { public: - DeclFromUser() : TaggedASTDecl<D>() { } - DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) { } + DeclFromUser() : TaggedASTDecl<D>() {} + DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) {} - DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx); + DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx); }; template <class D> -DeclFromUser<D> -DeclFromParser<D>::GetOrigin(ClangASTImporter *importer) -{ - DeclFromUser <> origin_decl; - importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); - if (origin_decl.IsInvalid()) - return DeclFromUser<D>(); - return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl)); +DeclFromUser<D> DeclFromParser<D>::GetOrigin(ClangASTImporter *importer) { + DeclFromUser<> origin_decl; + importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); + if (origin_decl.IsInvalid()) + return DeclFromUser<D>(); + return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl)); } template <class D> -DeclFromParser<D> -DeclFromUser<D>::Import(ClangASTImporter *importer, ASTContext &dest_ctx) -{ - DeclFromParser <> parser_generic_decl(importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl)); - if (parser_generic_decl.IsInvalid()) - return DeclFromParser<D>(); - return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl)); +DeclFromParser<D> DeclFromUser<D>::Import(ClangASTImporter *importer, + ASTContext &dest_ctx) { + DeclFromParser<> parser_generic_decl( + importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl)); + if (parser_generic_decl.IsInvalid()) + return DeclFromParser<D>(); + return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl)); } -static bool -FindObjCMethodDeclsWithOrigin (unsigned int current_id, - NameSearchContext &context, - ObjCInterfaceDecl *original_interface_decl, - clang::ASTContext *ast_context, - ClangASTImporter *ast_importer, - const char *log_info) -{ - const DeclarationName &decl_name(context.m_decl_name); - clang::ASTContext *original_ctx = &original_interface_decl->getASTContext(); - - Selector original_selector; - - if (decl_name.isObjCZeroArgSelector()) - { - IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString()); - original_selector = original_ctx->Selectors.getSelector(0, &ident); - } - else if (decl_name.isObjCOneArgSelector()) - { - const std::string &decl_name_string = decl_name.getAsString(); - std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1); - IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str()); - original_selector = original_ctx->Selectors.getSelector(1, &ident); +static bool FindObjCMethodDeclsWithOrigin( + unsigned int current_id, NameSearchContext &context, + ObjCInterfaceDecl *original_interface_decl, clang::ASTContext *ast_context, + ClangASTImporter *ast_importer, const char *log_info) { + const DeclarationName &decl_name(context.m_decl_name); + clang::ASTContext *original_ctx = &original_interface_decl->getASTContext(); + + Selector original_selector; + + if (decl_name.isObjCZeroArgSelector()) { + IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString()); + original_selector = original_ctx->Selectors.getSelector(0, &ident); + } else if (decl_name.isObjCOneArgSelector()) { + const std::string &decl_name_string = decl_name.getAsString(); + std::string decl_name_string_without_colon(decl_name_string.c_str(), + decl_name_string.length() - 1); + IdentifierInfo *ident = + &original_ctx->Idents.get(decl_name_string_without_colon.c_str()); + original_selector = original_ctx->Selectors.getSelector(1, &ident); + } else { + SmallVector<IdentifierInfo *, 4> idents; + + clang::Selector sel = decl_name.getObjCSelector(); + + unsigned num_args = sel.getNumArgs(); + + for (unsigned i = 0; i != num_args; ++i) { + idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i))); } - else - { - SmallVector<IdentifierInfo *, 4> idents; - clang::Selector sel = decl_name.getObjCSelector(); + original_selector = + original_ctx->Selectors.getSelector(num_args, idents.data()); + } - unsigned num_args = sel.getNumArgs(); + DeclarationName original_decl_name(original_selector); - for (unsigned i = 0; - i != num_args; - ++i) - { - idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i))); - } + llvm::SmallVector<NamedDecl *, 1> methods; - original_selector = original_ctx->Selectors.getSelector(num_args, idents.data()); - } + ClangASTContext::GetCompleteDecl(original_ctx, original_interface_decl); - DeclarationName original_decl_name(original_selector); - - llvm::SmallVector<NamedDecl *, 1> methods; - - ClangASTContext::GetCompleteDecl(original_ctx, original_interface_decl); - - if (ObjCMethodDecl *instance_method_decl = original_interface_decl->lookupInstanceMethod(original_selector)) - { - methods.push_back(instance_method_decl); - } - else if (ObjCMethodDecl *class_method_decl = original_interface_decl->lookupClassMethod(original_selector)) - { - methods.push_back(class_method_decl); - } - - if (methods.empty()) - { - return false; - } - - for (NamedDecl *named_decl : methods) - { - if (!named_decl) - continue; - - ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(named_decl); + if (ObjCMethodDecl *instance_method_decl = + original_interface_decl->lookupInstanceMethod(original_selector)) { + methods.push_back(instance_method_decl); + } else if (ObjCMethodDecl *class_method_decl = + original_interface_decl->lookupClassMethod( + original_selector)) { + methods.push_back(class_method_decl); + } - if (!result_method) - continue; + if (methods.empty()) { + return false; + } - Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method); + for (NamedDecl *named_decl : methods) { + if (!named_decl) + continue; - if (!copied_decl) - continue; + ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(named_decl); - ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl); + if (!result_method) + continue; - if (!copied_method_decl) - continue; + Decl *copied_decl = ast_importer->CopyDecl( + ast_context, &result_method->getASTContext(), result_method); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (!copied_decl) + continue; - if (log) - { - ASTDumper dumper((Decl*)copied_method_decl); - log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString()); - } + ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl); - context.AddNamedDecl(copied_method_decl); + if (!copied_method_decl) + continue; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) { + ASTDumper dumper((Decl *)copied_method_decl); + log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, + dumper.GetCString()); } - return true; + context.AddNamedDecl(copied_method_decl); + } + + return true; } -void -ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; - const DeclarationName &decl_name(context.m_decl_name); - const DeclContext *decl_ctx(context.m_decl_context); + const DeclarationName &decl_name(context.m_decl_name); + const DeclContext *decl_ctx(context.m_decl_context); - const ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl_ctx); + const ObjCInterfaceDecl *interface_decl = + dyn_cast<ObjCInterfaceDecl>(decl_ctx); - if (!interface_decl) - return; + if (!interface_decl) + return; - do - { - Decl *original_decl = NULL; - ASTContext *original_ctx = NULL; + do { + Decl *original_decl = NULL; + ASTContext *original_ctx = NULL; - m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx); + m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, + &original_ctx); - if (!original_decl) - break; + if (!original_decl) + break; - ObjCInterfaceDecl *original_interface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl); + ObjCInterfaceDecl *original_interface_decl = + dyn_cast<ObjCInterfaceDecl>(original_decl); - if (FindObjCMethodDeclsWithOrigin(current_id, - context, - original_interface_decl, - m_ast_context, - m_ast_importer_sp.get(), - "at origin")) - return; // found it, no need to look any further - } while (0); + if (FindObjCMethodDeclsWithOrigin(current_id, context, + original_interface_decl, m_ast_context, + m_ast_importer_sp.get(), "at origin")) + return; // found it, no need to look any further + } while (0); - StreamString ss; + StreamString ss; - if (decl_name.isObjCZeroArgSelector()) - { - ss.Printf("%s", decl_name.getAsString().c_str()); - } - else if (decl_name.isObjCOneArgSelector()) - { - ss.Printf("%s", decl_name.getAsString().c_str()); - } - else - { - clang::Selector sel = decl_name.getObjCSelector(); - - for (unsigned i = 0, e = sel.getNumArgs(); - i != e; - ++i) - { - llvm::StringRef r = sel.getNameForSlot(i); - ss.Printf("%s:", r.str().c_str()); - } + if (decl_name.isObjCZeroArgSelector()) { + ss.Printf("%s", decl_name.getAsString().c_str()); + } else if (decl_name.isObjCOneArgSelector()) { + ss.Printf("%s", decl_name.getAsString().c_str()); + } else { + clang::Selector sel = decl_name.getObjCSelector(); + + for (unsigned i = 0, e = sel.getNumArgs(); i != e; ++i) { + llvm::StringRef r = sel.getNameForSlot(i); + ss.Printf("%s:", r.str().c_str()); } - ss.Flush(); + } + ss.Flush(); - if (strstr(ss.GetData(), "$__lldb")) - return; // we don't need any results + if (strstr(ss.GetData(), "$__lldb")) + return; // we don't need any results - ConstString selector_name(ss.GetData()); + ConstString selector_name(ss.GetData()); - if (log) - log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p for selector [%s %s]", - current_id, static_cast<void*>(m_ast_context), - interface_decl->getNameAsString().c_str(), - selector_name.AsCString()); - SymbolContextList sc_list; + if (log) + log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p " + "for selector [%s %s]", + current_id, static_cast<void *>(m_ast_context), + interface_decl->getNameAsString().c_str(), + selector_name.AsCString()); + SymbolContextList sc_list; - const bool include_symbols = false; - const bool include_inlines = false; - const bool append = false; + const bool include_symbols = false; + const bool include_inlines = false; + const bool append = false; - std::string interface_name = interface_decl->getNameAsString(); + std::string interface_name = interface_decl->getNameAsString(); - do - { - StreamString ms; - ms.Printf("-[%s %s]", interface_name.c_str(), selector_name.AsCString()); - ms.Flush(); - ConstString instance_method_name(ms.GetData()); + do { + StreamString ms; + ms.Printf("-[%s %s]", interface_name.c_str(), selector_name.AsCString()); + ms.Flush(); + ConstString instance_method_name(ms.GetData()); - m_target->GetImages().FindFunctions(instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); + m_target->GetImages().FindFunctions( + instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, + include_inlines, append, sc_list); - if (sc_list.GetSize()) - break; + if (sc_list.GetSize()) + break; - ms.Clear(); - ms.Printf("+[%s %s]", interface_name.c_str(), selector_name.AsCString()); - ms.Flush(); - ConstString class_method_name(ms.GetData()); + ms.Clear(); + ms.Printf("+[%s %s]", interface_name.c_str(), selector_name.AsCString()); + ms.Flush(); + ConstString class_method_name(ms.GetData()); - m_target->GetImages().FindFunctions(class_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); + m_target->GetImages().FindFunctions( + class_method_name, lldb::eFunctionNameTypeFull, include_symbols, + include_inlines, append, sc_list); - if (sc_list.GetSize()) - break; + if (sc_list.GetSize()) + break; - // Fall back and check for methods in categories. If we find methods this way, we need to check that they're actually in - // categories on the desired class. + // Fall back and check for methods in categories. If we find methods this + // way, we need to check that they're actually in + // categories on the desired class. - SymbolContextList candidate_sc_list; + SymbolContextList candidate_sc_list; - m_target->GetImages().FindFunctions(selector_name, lldb::eFunctionNameTypeSelector, include_symbols, include_inlines, append, candidate_sc_list); + m_target->GetImages().FindFunctions( + selector_name, lldb::eFunctionNameTypeSelector, include_symbols, + include_inlines, append, candidate_sc_list); - for (uint32_t ci = 0, ce = candidate_sc_list.GetSize(); - ci != ce; - ++ci) - { - SymbolContext candidate_sc; + for (uint32_t ci = 0, ce = candidate_sc_list.GetSize(); ci != ce; ++ci) { + SymbolContext candidate_sc; - if (!candidate_sc_list.GetContextAtIndex(ci, candidate_sc)) - continue; + if (!candidate_sc_list.GetContextAtIndex(ci, candidate_sc)) + continue; - if (!candidate_sc.function) - continue; + if (!candidate_sc.function) + continue; - const char *candidate_name = candidate_sc.function->GetName().AsCString(); + const char *candidate_name = candidate_sc.function->GetName().AsCString(); - const char *cursor = candidate_name; + const char *cursor = candidate_name; - if (*cursor != '+' && *cursor != '-') - continue; + if (*cursor != '+' && *cursor != '-') + continue; - ++cursor; + ++cursor; - if (*cursor != '[') - continue; + if (*cursor != '[') + continue; - ++cursor; + ++cursor; - size_t interface_len = interface_name.length(); + size_t interface_len = interface_name.length(); - if (strncmp(cursor, interface_name.c_str(), interface_len)) - continue; + if (strncmp(cursor, interface_name.c_str(), interface_len)) + continue; - cursor += interface_len; + cursor += interface_len; - if (*cursor == ' ' || *cursor == '(') - sc_list.Append(candidate_sc); - } + if (*cursor == ' ' || *cursor == '(') + sc_list.Append(candidate_sc); } - while (0); - - if (sc_list.GetSize()) - { - // We found a good function symbol. Use that. + } while (0); - for (uint32_t i = 0, e = sc_list.GetSize(); - i != e; - ++i) - { - SymbolContext sc; + if (sc_list.GetSize()) { + // We found a good function symbol. Use that. - if (!sc_list.GetContextAtIndex(i, sc)) - continue; + for (uint32_t i = 0, e = sc_list.GetSize(); i != e; ++i) { + SymbolContext sc; - if (!sc.function) - continue; + if (!sc_list.GetContextAtIndex(i, sc)) + continue; - CompilerDeclContext function_decl_ctx = sc.function->GetDeclContext(); - if (!function_decl_ctx) - continue; + if (!sc.function) + continue; - ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); + CompilerDeclContext function_decl_ctx = sc.function->GetDeclContext(); + if (!function_decl_ctx) + continue; - if (!method_decl) - continue; + ObjCMethodDecl *method_decl = + ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); - ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface(); + if (!method_decl) + continue; - if (!found_interface_decl) - continue; + ObjCInterfaceDecl *found_interface_decl = + method_decl->getClassInterface(); - if (found_interface_decl->getName() == interface_decl->getName()) - { - Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl); + if (!found_interface_decl) + continue; - if (!copied_decl) - continue; + if (found_interface_decl->getName() == interface_decl->getName()) { + Decl *copied_decl = m_ast_importer_sp->CopyDecl( + m_ast_context, &method_decl->getASTContext(), method_decl); - ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl); + if (!copied_decl) + continue; - if (!copied_method_decl) - continue; + ObjCMethodDecl *copied_method_decl = + dyn_cast<ObjCMethodDecl>(copied_decl); - if (log) - { - ASTDumper dumper((Decl*)copied_method_decl); - log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, dumper.GetCString()); - } + if (!copied_method_decl) + continue; - context.AddNamedDecl(copied_method_decl); - } + if (log) { + ASTDumper dumper((Decl *)copied_method_decl); + log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, + dumper.GetCString()); } - return; + context.AddNamedDecl(copied_method_decl); + } } - // Try the debug information. + return; + } - do - { - ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(interface_decl)); + // Try the debug information. - if (!complete_interface_decl) - break; + do { + ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface( + const_cast<ObjCInterfaceDecl *>(interface_decl)); - // We found the complete interface. The runtime never needs to be queried in this scenario. + if (!complete_interface_decl) + break; - DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl); + // We found the complete interface. The runtime never needs to be queried + // in this scenario. - if (complete_interface_decl == interface_decl) - break; // already checked this one + DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl( + complete_interface_decl); - if (log) - log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, static_cast<void*>(complete_interface_decl), - static_cast<void*>(&complete_iface_decl->getASTContext())); + if (complete_interface_decl == interface_decl) + break; // already checked this one + + if (log) + log->Printf("CAS::FOPD[%d] trying origin " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, static_cast<void *>(complete_interface_decl), + static_cast<void *>(&complete_iface_decl->getASTContext())); + + FindObjCMethodDeclsWithOrigin(current_id, context, complete_interface_decl, + m_ast_context, m_ast_importer_sp.get(), + "in debug info"); + + return; + } while (0); + + do { + // Check the modules only if the debug information didn't have a complete + // interface. + + if (ClangModulesDeclVendor *modules_decl_vendor = + m_target->GetClangModulesDeclVendor()) { + ConstString interface_name(interface_decl->getNameAsString().c_str()); + bool append = false; + uint32_t max_matches = 1; + std::vector<clang::NamedDecl *> decls; + + if (!modules_decl_vendor->FindDecls(interface_name, append, max_matches, + decls)) + break; + + ObjCInterfaceDecl *interface_decl_from_modules = + dyn_cast<ObjCInterfaceDecl>(decls[0]); - FindObjCMethodDeclsWithOrigin(current_id, - context, - complete_interface_decl, - m_ast_context, - m_ast_importer_sp.get(), - "in debug info"); + if (!interface_decl_from_modules) + break; + if (FindObjCMethodDeclsWithOrigin( + current_id, context, interface_decl_from_modules, m_ast_context, + m_ast_importer_sp.get(), "in modules")) return; } - while (0); - - do - { - // Check the modules only if the debug information didn't have a complete interface. - - if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) - { - ConstString interface_name(interface_decl->getNameAsString().c_str()); - bool append = false; - uint32_t max_matches = 1; - std::vector <clang::NamedDecl *> decls; - - if (!modules_decl_vendor->FindDecls(interface_name, - append, - max_matches, - decls)) - break; - - ObjCInterfaceDecl *interface_decl_from_modules = dyn_cast<ObjCInterfaceDecl>(decls[0]); - - if (!interface_decl_from_modules) - break; - - if (FindObjCMethodDeclsWithOrigin(current_id, - context, - interface_decl_from_modules, - m_ast_context, - m_ast_importer_sp.get(), - "in modules")) - return; - } - } - while (0); + } while (0); - do - { - // Check the runtime only if the debug information didn't have a complete interface and the modules don't get us anywhere. + do { + // Check the runtime only if the debug information didn't have a complete + // interface and the modules don't get us anywhere. - lldb::ProcessSP process(m_target->GetProcessSP()); + lldb::ProcessSP process(m_target->GetProcessSP()); - if (!process) - break; + if (!process) + break; - ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); - if (!language_runtime) - break; + if (!language_runtime) + break; - DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); - if (!decl_vendor) - break; + if (!decl_vendor) + break; - ConstString interface_name(interface_decl->getNameAsString().c_str()); - bool append = false; - uint32_t max_matches = 1; - std::vector <clang::NamedDecl *> decls; + ConstString interface_name(interface_decl->getNameAsString().c_str()); + bool append = false; + uint32_t max_matches = 1; + std::vector<clang::NamedDecl *> decls; - if (!decl_vendor->FindDecls(interface_name, - append, - max_matches, - decls)) - break; + if (!decl_vendor->FindDecls(interface_name, append, max_matches, decls)) + break; - ObjCInterfaceDecl *runtime_interface_decl = dyn_cast<ObjCInterfaceDecl>(decls[0]); - - if (!runtime_interface_decl) - break; + ObjCInterfaceDecl *runtime_interface_decl = + dyn_cast<ObjCInterfaceDecl>(decls[0]); - FindObjCMethodDeclsWithOrigin(current_id, - context, - runtime_interface_decl, - m_ast_context, - m_ast_importer_sp.get(), - "in runtime"); - } - while(0); + if (!runtime_interface_decl) + break; + + FindObjCMethodDeclsWithOrigin(current_id, context, runtime_interface_decl, + m_ast_context, m_ast_importer_sp.get(), + "in runtime"); + } while (0); } -static bool -FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, - NameSearchContext &context, - clang::ASTContext &ast_context, - ClangASTImporter *ast_importer, - DeclFromUser<const ObjCInterfaceDecl> &origin_iface_decl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +static bool FindObjCPropertyAndIvarDeclsWithOrigin( + unsigned int current_id, NameSearchContext &context, + clang::ASTContext &ast_context, ClangASTImporter *ast_importer, + DeclFromUser<const ObjCInterfaceDecl> &origin_iface_decl) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (origin_iface_decl.IsInvalid()) + return false; + + std::string name_str = context.m_decl_name.getAsString(); + StringRef name(name_str.c_str()); + IdentifierInfo &name_identifier( + origin_iface_decl->getASTContext().Idents.get(name)); + + DeclFromUser<ObjCPropertyDecl> origin_property_decl( + origin_iface_decl->FindPropertyDeclaration( + &name_identifier, ObjCPropertyQueryKind::OBJC_PR_query_instance)); + + bool found = false; + + if (origin_property_decl.IsValid()) { + DeclFromParser<ObjCPropertyDecl> parser_property_decl( + origin_property_decl.Import(ast_importer, ast_context)); + if (parser_property_decl.IsValid()) { + if (log) { + ASTDumper dumper((Decl *)parser_property_decl.decl); + log->Printf(" CAS::FOPD[%d] found %s", current_id, + dumper.GetCString()); + } + + context.AddNamedDecl(parser_property_decl.decl); + found = true; + } + } + + DeclFromUser<ObjCIvarDecl> origin_ivar_decl( + origin_iface_decl->getIvarDecl(&name_identifier)); + + if (origin_ivar_decl.IsValid()) { + DeclFromParser<ObjCIvarDecl> parser_ivar_decl( + origin_ivar_decl.Import(ast_importer, ast_context)); + if (parser_ivar_decl.IsValid()) { + if (log) { + ASTDumper dumper((Decl *)parser_ivar_decl.decl); + log->Printf(" CAS::FOPD[%d] found %s", current_id, + dumper.GetCString()); + } + + context.AddNamedDecl(parser_ivar_decl.decl); + found = true; + } + } - if (origin_iface_decl.IsInvalid()) - return false; + return found; +} - std::string name_str = context.m_decl_name.getAsString(); - StringRef name(name_str.c_str()); - IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name)); +void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier, ObjCPropertyQueryKind::OBJC_PR_query_instance)); + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; - bool found = false; + DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl( + cast<ObjCInterfaceDecl>(context.m_decl_context)); + DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl( + parser_iface_decl.GetOrigin(m_ast_importer_sp.get())); - if (origin_property_decl.IsValid()) - { - DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(ast_importer, ast_context)); - if (parser_property_decl.IsValid()) - { - if (log) - { - ASTDumper dumper((Decl*)parser_property_decl.decl); - log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); - } + ConstString class_name(parser_iface_decl->getNameAsString().c_str()); - context.AddNamedDecl(parser_property_decl.decl); - found = true; - } - } + if (log) + log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on " + "(ASTContext*)%p for '%s.%s'", + current_id, static_cast<void *>(m_ast_context), + parser_iface_decl->getNameAsString().c_str(), + context.m_decl_name.getAsString().c_str()); - DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier)); - - if (origin_ivar_decl.IsValid()) - { - DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(ast_importer, ast_context)); - if (parser_ivar_decl.IsValid()) - { - if (log) - { - ASTDumper dumper((Decl*)parser_ivar_decl.decl); - log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); - } + if (FindObjCPropertyAndIvarDeclsWithOrigin( + current_id, context, *m_ast_context, m_ast_importer_sp.get(), + origin_iface_decl)) + return; - context.AddNamedDecl(parser_ivar_decl.decl); - found = true; - } - } + if (log) + log->Printf("CAS::FOPD[%d] couldn't find the property on origin " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching " + "elsewhere...", + current_id, static_cast<const void *>(origin_iface_decl.decl), + static_cast<void *>(&origin_iface_decl->getASTContext())); - return found; -} + SymbolContext null_sc; + TypeList type_list; -void -ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + do { + ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface( + const_cast<ObjCInterfaceDecl *>(parser_iface_decl.decl)); - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; + if (!complete_interface_decl) + break; - DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context)); - DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer_sp.get())); + // We found the complete interface. The runtime never needs to be queried + // in this scenario. - ConstString class_name(parser_iface_decl->getNameAsString().c_str()); + DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl( + complete_interface_decl); - if (log) - log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'", - current_id, static_cast<void*>(m_ast_context), - parser_iface_decl->getNameAsString().c_str(), - context.m_decl_name.getAsString().c_str()); - - if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, - context, - *m_ast_context, - m_ast_importer_sp.get(), - origin_iface_decl)) - return; + if (complete_iface_decl.decl == origin_iface_decl.decl) + break; // already checked this one if (log) - log->Printf("CAS::FOPD[%d] couldn't find the property on origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching elsewhere...", - current_id, static_cast<const void*>(origin_iface_decl.decl), - static_cast<void*>(&origin_iface_decl->getASTContext())); + log->Printf("CAS::FOPD[%d] trying origin " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + static_cast<const void *>(complete_iface_decl.decl), + static_cast<void *>(&complete_iface_decl->getASTContext())); - SymbolContext null_sc; - TypeList type_list; + FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *m_ast_context, + m_ast_importer_sp.get(), + complete_iface_decl); - do - { - ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(parser_iface_decl.decl)); + return; + } while (0); - if (!complete_interface_decl) - break; + do { + // Check the modules only if the debug information didn't have a complete + // interface. - // We found the complete interface. The runtime never needs to be queried in this scenario. + ClangModulesDeclVendor *modules_decl_vendor = + m_target->GetClangModulesDeclVendor(); - DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl); + if (!modules_decl_vendor) + break; - if (complete_iface_decl.decl == origin_iface_decl.decl) - break; // already checked this one + bool append = false; + uint32_t max_matches = 1; + std::vector<clang::NamedDecl *> decls; - if (log) - log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast<const void*>(complete_iface_decl.decl), - static_cast<void*>(&complete_iface_decl->getASTContext())); + if (!modules_decl_vendor->FindDecls(class_name, append, max_matches, decls)) + break; - FindObjCPropertyAndIvarDeclsWithOrigin(current_id, - context, - *m_ast_context, - m_ast_importer_sp.get(), - complete_iface_decl); + DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_modules( + dyn_cast<ObjCInterfaceDecl>(decls[0])); - return; - } - while(0); - - do - { - // Check the modules only if the debug information didn't have a complete interface. - - ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor(); - - if (!modules_decl_vendor) - break; - - bool append = false; - uint32_t max_matches = 1; - std::vector <clang::NamedDecl *> decls; - - if (!modules_decl_vendor->FindDecls(class_name, - append, - max_matches, - decls)) - break; - - DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_modules(dyn_cast<ObjCInterfaceDecl>(decls[0])); - - if (!interface_decl_from_modules.IsValid()) - break; - - if (log) - log->Printf("CAS::FOPD[%d] trying module (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast<const void*>(interface_decl_from_modules.decl), - static_cast<void*>(&interface_decl_from_modules->getASTContext())); - - if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, - context, - *m_ast_context, - m_ast_importer_sp.get(), - interface_decl_from_modules)) - return; - } - while(0); + if (!interface_decl_from_modules.IsValid()) + break; - do - { - // Check the runtime only if the debug information didn't have a complete interface - // and nothing was in the modules. + if (log) + log->Printf( + "CAS::FOPD[%d] trying module " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + static_cast<const void *>(interface_decl_from_modules.decl), + static_cast<void *>(&interface_decl_from_modules->getASTContext())); + + if (FindObjCPropertyAndIvarDeclsWithOrigin( + current_id, context, *m_ast_context, m_ast_importer_sp.get(), + interface_decl_from_modules)) + return; + } while (0); + + do { + // Check the runtime only if the debug information didn't have a complete + // interface + // and nothing was in the modules. - lldb::ProcessSP process(m_target->GetProcessSP()); + lldb::ProcessSP process(m_target->GetProcessSP()); - if (!process) - return; + if (!process) + return; - ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); - if (!language_runtime) - return; + if (!language_runtime) + return; - DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); - if (!decl_vendor) - break; + if (!decl_vendor) + break; - bool append = false; - uint32_t max_matches = 1; - std::vector <clang::NamedDecl *> decls; + bool append = false; + uint32_t max_matches = 1; + std::vector<clang::NamedDecl *> decls; - if (!decl_vendor->FindDecls(class_name, - append, - max_matches, - decls)) - break; + if (!decl_vendor->FindDecls(class_name, append, max_matches, decls)) + break; - DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_runtime(dyn_cast<ObjCInterfaceDecl>(decls[0])); - - if (!interface_decl_from_runtime.IsValid()) - break; + DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_runtime( + dyn_cast<ObjCInterfaceDecl>(decls[0])); - if (log) - log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast<const void*>(interface_decl_from_runtime.decl), - static_cast<void*>(&interface_decl_from_runtime->getASTContext())); - - if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, - context, - *m_ast_context, - m_ast_importer_sp.get(), - interface_decl_from_runtime)) - return; - } - while(0); + if (!interface_decl_from_runtime.IsValid()) + break; + + if (log) + log->Printf( + "CAS::FOPD[%d] trying runtime " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + static_cast<const void *>(interface_decl_from_runtime.decl), + static_cast<void *>(&interface_decl_from_runtime->getASTContext())); + + if (FindObjCPropertyAndIvarDeclsWithOrigin( + current_id, context, *m_ast_context, m_ast_importer_sp.get(), + interface_decl_from_runtime)) + return; + } while (0); } typedef llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsetMap; typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetMap; template <class D, class O> -static bool -ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, llvm::DenseMap<const D *, O> &source_map, - ClangASTImporter *importer, ASTContext &dest_ctx) -{ - // When importing fields into a new record, clang has a hard requirement that - // fields be imported in field offset order. Since they are stored in a DenseMap - // with a pointer as the key type, this means we cannot simply iterate over the - // map, as the order will be non-deterministic. Instead we have to sort by the offset - // and then insert in sorted order. - typedef llvm::DenseMap<const D *, O> MapType; - typedef typename MapType::value_type PairType; - std::vector<PairType> sorted_items; - sorted_items.reserve(source_map.size()); - sorted_items.assign(source_map.begin(), source_map.end()); - std::sort(sorted_items.begin(), sorted_items.end(), - [](const PairType &lhs, const PairType &rhs) - { - return lhs.second < rhs.second; - }); - - for (const auto &item : sorted_items) - { - DeclFromUser<D> user_decl(const_cast<D *>(item.first)); - DeclFromParser <D> parser_decl(user_decl.Import(importer, dest_ctx)); - if (parser_decl.IsInvalid()) - return false; - destination_map.insert(std::pair<const D *, O>(parser_decl.decl, item.second)); - } +static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, + llvm::DenseMap<const D *, O> &source_map, + ClangASTImporter *importer, ASTContext &dest_ctx) { + // When importing fields into a new record, clang has a hard requirement that + // fields be imported in field offset order. Since they are stored in a + // DenseMap + // with a pointer as the key type, this means we cannot simply iterate over + // the + // map, as the order will be non-deterministic. Instead we have to sort by + // the offset + // and then insert in sorted order. + typedef llvm::DenseMap<const D *, O> MapType; + typedef typename MapType::value_type PairType; + std::vector<PairType> sorted_items; + sorted_items.reserve(source_map.size()); + sorted_items.assign(source_map.begin(), source_map.end()); + std::sort(sorted_items.begin(), sorted_items.end(), + [](const PairType &lhs, const PairType &rhs) { + return lhs.second < rhs.second; + }); + + for (const auto &item : sorted_items) { + DeclFromUser<D> user_decl(const_cast<D *>(item.first)); + DeclFromParser<D> parser_decl(user_decl.Import(importer, dest_ctx)); + if (parser_decl.IsInvalid()) + return false; + destination_map.insert( + std::pair<const D *, O>(parser_decl.decl, item.second)); + } - return true; + return true; } template <bool IsVirtual> -bool -ExtractBaseOffsets(const ASTRecordLayout &record_layout, DeclFromUser<const CXXRecordDecl> &record, - BaseOffsetMap &base_offsets) -{ - for (CXXRecordDecl::base_class_const_iterator bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()), - be = (IsVirtual ? record->vbases_end() : record->bases_end()); - bi != be; ++bi) - { - if (!IsVirtual && bi->isVirtual()) - continue; +bool ExtractBaseOffsets(const ASTRecordLayout &record_layout, + DeclFromUser<const CXXRecordDecl> &record, + BaseOffsetMap &base_offsets) { + for (CXXRecordDecl::base_class_const_iterator + bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()), + be = (IsVirtual ? record->vbases_end() : record->bases_end()); + bi != be; ++bi) { + if (!IsVirtual && bi->isVirtual()) + continue; + + const clang::Type *origin_base_type = bi->getType().getTypePtr(); + const clang::RecordType *origin_base_record_type = + origin_base_type->getAs<RecordType>(); + + if (!origin_base_record_type) + return false; - const clang::Type *origin_base_type = bi->getType().getTypePtr(); - const clang::RecordType *origin_base_record_type = origin_base_type->getAs<RecordType>(); + DeclFromUser<RecordDecl> origin_base_record( + origin_base_record_type->getDecl()); - if (!origin_base_record_type) - return false; + if (origin_base_record.IsInvalid()) + return false; - DeclFromUser <RecordDecl> origin_base_record(origin_base_record_type->getDecl()); + DeclFromUser<CXXRecordDecl> origin_base_cxx_record( + DynCast<CXXRecordDecl>(origin_base_record)); - if (origin_base_record.IsInvalid()) - return false; + if (origin_base_cxx_record.IsInvalid()) + return false; - DeclFromUser <CXXRecordDecl> origin_base_cxx_record(DynCast<CXXRecordDecl>(origin_base_record)); + CharUnits base_offset; - if (origin_base_cxx_record.IsInvalid()) - return false; + if (IsVirtual) + base_offset = + record_layout.getVBaseClassOffset(origin_base_cxx_record.decl); + else + base_offset = + record_layout.getBaseClassOffset(origin_base_cxx_record.decl); - CharUnits base_offset; + base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>( + origin_base_cxx_record.decl, base_offset)); + } - if (IsVirtual) - base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl); - else - base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl); + return true; +} - base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>(origin_base_cxx_record.decl, base_offset)); - } +bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, + uint64_t &alignment, + FieldOffsetMap &field_offsets, + BaseOffsetMap &base_offsets, + BaseOffsetMap &virtual_base_offsets) { + ClangASTMetrics::RegisterRecordLayout(); - return true; -} + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; -bool -ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, uint64_t &alignment, - FieldOffsetMap &field_offsets, BaseOffsetMap &base_offsets, - BaseOffsetMap &virtual_base_offsets) -{ - ClangASTMetrics::RegisterRecordLayout(); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; + if (log) + log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p " + "[name = '%s']", + current_id, static_cast<void *>(m_ast_context), + static_cast<const void *>(record), + record->getNameAsString().c_str()); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + DeclFromParser<const RecordDecl> parser_record(record); + DeclFromUser<const RecordDecl> origin_record( + parser_record.GetOrigin(m_ast_importer_sp.get())); - if (log) - log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p [name = '%s']", - current_id, static_cast<void*>(m_ast_context), - static_cast<const void*>(record), - record->getNameAsString().c_str()); + if (origin_record.IsInvalid()) + return false; + + FieldOffsetMap origin_field_offsets; + BaseOffsetMap origin_base_offsets; + BaseOffsetMap origin_virtual_base_offsets; - DeclFromParser <const RecordDecl> parser_record(record); - DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer_sp.get())); + ClangASTContext::GetCompleteDecl( + &origin_record->getASTContext(), + const_cast<RecordDecl *>(origin_record.decl)); - if (origin_record.IsInvalid()) - return false; + clang::RecordDecl *definition = origin_record.decl->getDefinition(); + if (!definition || !definition->isCompleteDefinition()) + return false; - FieldOffsetMap origin_field_offsets; - BaseOffsetMap origin_base_offsets; - BaseOffsetMap origin_virtual_base_offsets; + const ASTRecordLayout &record_layout( + origin_record->getASTContext().getASTRecordLayout(origin_record.decl)); - ClangASTContext::GetCompleteDecl(&origin_record->getASTContext(), const_cast<RecordDecl*>(origin_record.decl)); + int field_idx = 0, field_count = record_layout.getFieldCount(); - clang::RecordDecl* definition = origin_record.decl->getDefinition(); - if (!definition || !definition->isCompleteDefinition()) - return false; + for (RecordDecl::field_iterator fi = origin_record->field_begin(), + fe = origin_record->field_end(); + fi != fe; ++fi) { + if (field_idx >= field_count) + return false; // Layout didn't go well. Bail out. - const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl)); + uint64_t field_offset = record_layout.getFieldOffset(field_idx); - int field_idx = 0, field_count = record_layout.getFieldCount(); + origin_field_offsets.insert( + std::pair<const FieldDecl *, uint64_t>(*fi, field_offset)); - for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end(); fi != fe; ++fi) - { - if (field_idx >= field_count) - return false; // Layout didn't go well. Bail out. + field_idx++; + } - uint64_t field_offset = record_layout.getFieldOffset(field_idx); + ASTContext &parser_ast_context(record->getASTContext()); - origin_field_offsets.insert(std::pair<const FieldDecl *, uint64_t>(*fi, field_offset)); + DeclFromUser<const CXXRecordDecl> origin_cxx_record( + DynCast<const CXXRecordDecl>(origin_record)); - field_idx++; + if (origin_cxx_record.IsValid()) { + if (!ExtractBaseOffsets<false>(record_layout, origin_cxx_record, + origin_base_offsets) || + !ExtractBaseOffsets<true>(record_layout, origin_cxx_record, + origin_virtual_base_offsets)) + return false; + } + + if (!ImportOffsetMap(field_offsets, origin_field_offsets, + m_ast_importer_sp.get(), parser_ast_context) || + !ImportOffsetMap(base_offsets, origin_base_offsets, + m_ast_importer_sp.get(), parser_ast_context) || + !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, + m_ast_importer_sp.get(), parser_ast_context)) + return false; + + size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth(); + alignment = record_layout.getAlignment().getQuantity() * + m_ast_context->getCharWidth(); + + if (log) { + log->Printf("LRT[%u] returned:", current_id); + log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id, + static_cast<const void *>(origin_record.decl)); + log->Printf("LRT[%u] Size = %" PRId64, current_id, size); + log->Printf("LRT[%u] Alignment = %" PRId64, current_id, alignment); + log->Printf("LRT[%u] Fields:", current_id); + for (RecordDecl::field_iterator fi = record->field_begin(), + fe = record->field_end(); + fi != fe; ++fi) { + log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 + " bits", + current_id, static_cast<void *>(*fi), + fi->getNameAsString().c_str(), field_offsets[*fi]); } + DeclFromParser<const CXXRecordDecl> parser_cxx_record = + DynCast<const CXXRecordDecl>(parser_record); + if (parser_cxx_record.IsValid()) { + log->Printf("LRT[%u] Bases:", current_id); + for (CXXRecordDecl::base_class_const_iterator + bi = parser_cxx_record->bases_begin(), + be = parser_cxx_record->bases_end(); + bi != be; ++bi) { + bool is_virtual = bi->isVirtual(); + + QualType base_type = bi->getType(); + const RecordType *base_record_type = base_type->getAs<RecordType>(); + DeclFromParser<RecordDecl> base_record(base_record_type->getDecl()); + DeclFromParser<CXXRecordDecl> base_cxx_record = + DynCast<CXXRecordDecl>(base_record); + + log->Printf( + "LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 + " chars", + current_id, (is_virtual ? "Virtual " : ""), + static_cast<void *>(base_cxx_record.decl), + base_cxx_record.decl->getNameAsString().c_str(), + (is_virtual + ? virtual_base_offsets[base_cxx_record.decl].getQuantity() + : base_offsets[base_cxx_record.decl].getQuantity())); + } + } else { + log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id); + } + } - ASTContext &parser_ast_context(record->getASTContext()); + return true; +} - DeclFromUser <const CXXRecordDecl> origin_cxx_record(DynCast<const CXXRecordDecl>(origin_record)); +void ClangASTSource::CompleteNamespaceMap( + ClangASTImporter::NamespaceMapSP &namespace_map, const ConstString &name, + ClangASTImporter::NamespaceMapSP &parent_map) const { + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) { + if (parent_map && parent_map->size()) + log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for " + "namespace %s in namespace %s", + current_id, static_cast<void *>(m_ast_context), + name.GetCString(), + parent_map->begin()->second.GetName().AsCString()); + else + log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for " + "namespace %s", + current_id, static_cast<void *>(m_ast_context), + name.GetCString()); + } - if (origin_cxx_record.IsValid()) - { - if (!ExtractBaseOffsets<false>(record_layout, origin_cxx_record, origin_base_offsets) || - !ExtractBaseOffsets<true>(record_layout, origin_cxx_record, origin_virtual_base_offsets)) - return false; - } + if (parent_map) { + for (ClangASTImporter::NamespaceMap::iterator i = parent_map->begin(), + e = parent_map->end(); + i != e; ++i) { + CompilerDeclContext found_namespace_decl; - if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer_sp.get(), parser_ast_context) || - !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer_sp.get(), parser_ast_context) || - !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer_sp.get(), parser_ast_context)) - return false; + lldb::ModuleSP module_sp = i->first; + CompilerDeclContext module_parent_namespace_decl = i->second; - size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth(); - alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth(); + SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); - if (log) - { - log->Printf("LRT[%u] returned:", current_id); - log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id, - static_cast<const void*>(origin_record.decl)); - log->Printf("LRT[%u] Size = %" PRId64, current_id, size); - log->Printf("LRT[%u] Alignment = %" PRId64, current_id, alignment); - log->Printf("LRT[%u] Fields:", current_id); - for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end(); - fi != fe; - ++fi) - { - log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits", current_id, - static_cast<void *>(*fi), fi->getNameAsString().c_str(), field_offsets[*fi]); - } - DeclFromParser <const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record); - if (parser_cxx_record.IsValid()) - { - log->Printf("LRT[%u] Bases:", current_id); - for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end(); - bi != be; - ++bi) - { - bool is_virtual = bi->isVirtual(); - - QualType base_type = bi->getType(); - const RecordType *base_record_type = base_type->getAs<RecordType>(); - DeclFromParser <RecordDecl> base_record(base_record_type->getDecl()); - DeclFromParser <CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record); - - log->Printf("LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars", current_id, - (is_virtual ? "Virtual " : ""), static_cast<void *>(base_cxx_record.decl), - base_cxx_record.decl->getNameAsString().c_str(), - (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity() - : base_offsets[base_cxx_record.decl].getQuantity())); - } - } - else - { - log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id); - } - } + if (!symbol_vendor) + continue; - return true; -} + SymbolContext null_sc; -void -ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespace_map, - const ConstString &name, - ClangASTImporter::NamespaceMapSP &parent_map) const -{ - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; + found_namespace_decl = symbol_vendor->FindNamespace( + null_sc, name, &module_parent_namespace_decl); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (!found_namespace_decl) + continue; - if (log) - { - if (parent_map && parent_map->size()) - log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s in namespace %s", - current_id, static_cast<void*>(m_ast_context), - name.GetCString(), - parent_map->begin()->second.GetName().AsCString()); - else - log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s", - current_id, static_cast<void*>(m_ast_context), - name.GetCString()); + namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>( + module_sp, found_namespace_decl)); + + if (log) + log->Printf(" CMN[%u] Found namespace %s in module %s", current_id, + name.GetCString(), + module_sp->GetFileSpec().GetFilename().GetCString()); } + } else { + const ModuleList &target_images = m_target->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); - if (parent_map) - { - for (ClangASTImporter::NamespaceMap::iterator i = parent_map->begin(), e = parent_map->end(); - i != e; - ++i) - { - CompilerDeclContext found_namespace_decl; + CompilerDeclContext null_namespace_decl; - lldb::ModuleSP module_sp = i->first; - CompilerDeclContext module_parent_namespace_decl = i->second; + for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) { + lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); - SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); + if (!image) + continue; - if (!symbol_vendor) - continue; + CompilerDeclContext found_namespace_decl; - SymbolContext null_sc; + SymbolVendor *symbol_vendor = image->GetSymbolVendor(); - found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &module_parent_namespace_decl); + if (!symbol_vendor) + continue; - if (!found_namespace_decl) - continue; + SymbolContext null_sc; - namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(module_sp, found_namespace_decl)); + found_namespace_decl = + symbol_vendor->FindNamespace(null_sc, name, &null_namespace_decl); - if (log) - log->Printf(" CMN[%u] Found namespace %s in module %s", - current_id, - name.GetCString(), - module_sp->GetFileSpec().GetFilename().GetCString()); - } + if (!found_namespace_decl) + continue; + + namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>( + image, found_namespace_decl)); + + if (log) + log->Printf(" CMN[%u] Found namespace %s in module %s", current_id, + name.GetCString(), + image->GetFileSpec().GetFilename().GetCString()); } - else - { - const ModuleList &target_images = m_target->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); + } +} - CompilerDeclContext null_namespace_decl; +NamespaceDecl *ClangASTSource::AddNamespace( + NameSearchContext &context, + ClangASTImporter::NamespaceMapSP &namespace_decls) { + if (!namespace_decls) + return nullptr; - for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) - { - lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); + const CompilerDeclContext &namespace_decl = namespace_decls->begin()->second; - if (!image) - continue; + clang::ASTContext *src_ast = + ClangASTContext::DeclContextGetClangASTContext(namespace_decl); + if (!src_ast) + return nullptr; + clang::NamespaceDecl *src_namespace_decl = + ClangASTContext::DeclContextGetAsNamespaceDecl(namespace_decl); - CompilerDeclContext found_namespace_decl; + if (!src_namespace_decl) + return nullptr; - SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + Decl *copied_decl = + m_ast_importer_sp->CopyDecl(m_ast_context, src_ast, src_namespace_decl); - if (!symbol_vendor) - continue; + if (!copied_decl) + return nullptr; - SymbolContext null_sc; + NamespaceDecl *copied_namespace_decl = dyn_cast<NamespaceDecl>(copied_decl); - found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &null_namespace_decl); + if (!copied_namespace_decl) + return nullptr; - if (!found_namespace_decl) - continue; + context.m_decls.push_back(copied_namespace_decl); - namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(image, found_namespace_decl)); + m_ast_importer_sp->RegisterNamespaceMap(copied_namespace_decl, + namespace_decls); - if (log) - log->Printf(" CMN[%u] Found namespace %s in module %s", - current_id, - name.GetCString(), - image->GetFileSpec().GetFilename().GetCString()); - } - } + return dyn_cast<NamespaceDecl>(copied_decl); } -NamespaceDecl * -ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::NamespaceMapSP &namespace_decls) -{ - if (!namespace_decls) - return nullptr; +CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { + ClangASTContext *src_ast = + llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem()); + if (src_ast == nullptr) + return CompilerType(); - const CompilerDeclContext &namespace_decl = namespace_decls->begin()->second; + ClangASTMetrics::RegisterLLDBImport(); - clang::ASTContext *src_ast = ClangASTContext::DeclContextGetClangASTContext(namespace_decl); - if (!src_ast) - return nullptr; - clang::NamespaceDecl *src_namespace_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(namespace_decl); + SetImportInProgress(true); - if (!src_namespace_decl) - return nullptr; + QualType copied_qual_type = + m_ast_importer_sp->CopyType(m_ast_context, src_ast->getASTContext(), + ClangUtil::GetQualType(src_type)); - Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, src_ast, src_namespace_decl); + SetImportInProgress(false); - if (!copied_decl) - return nullptr; + if (copied_qual_type.getAsOpaquePtr() && + copied_qual_type->getCanonicalTypeInternal().isNull()) + // this shouldn't happen, but we're hardening because the AST importer seems + // to be generating bad types + // on occasion. + return CompilerType(); - NamespaceDecl *copied_namespace_decl = dyn_cast<NamespaceDecl>(copied_decl); + return CompilerType(m_ast_context, copied_qual_type); +} + +clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) { + assert(type && "Type for variable must be valid!"); - if (!copied_namespace_decl) - return nullptr; + if (!type.IsValid()) + return NULL; + + ClangASTContext *lldb_ast = + llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); + if (!lldb_ast) + return NULL; - context.m_decls.push_back(copied_namespace_decl); + IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo(); - m_ast_importer_sp->RegisterNamespaceMap(copied_namespace_decl, namespace_decls); + clang::ASTContext *ast = lldb_ast->getASTContext(); - return dyn_cast<NamespaceDecl>(copied_decl); + clang::NamedDecl *Decl = VarDecl::Create( + *ast, const_cast<DeclContext *>(m_decl_context), SourceLocation(), + SourceLocation(), ii, ClangUtil::GetQualType(type), 0, SC_Static); + m_decls.push_back(Decl); + + return Decl; } -CompilerType -ClangASTSource::GuardedCopyType (const CompilerType &src_type) -{ - ClangASTContext *src_ast = llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem()); - if (src_ast == nullptr) - return CompilerType(); +clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, + bool extern_c) { + assert(type && "Type for variable must be valid!"); - ClangASTMetrics::RegisterLLDBImport(); + if (!type.IsValid()) + return NULL; - SetImportInProgress(true); + if (m_function_types.count(type)) + return NULL; - QualType copied_qual_type = - m_ast_importer_sp->CopyType(m_ast_context, src_ast->getASTContext(), ClangUtil::GetQualType(src_type)); + ClangASTContext *lldb_ast = + llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); + if (!lldb_ast) + return NULL; - SetImportInProgress(false); + m_function_types.insert(type); - if (copied_qual_type.getAsOpaquePtr() && copied_qual_type->getCanonicalTypeInternal().isNull()) - // this shouldn't happen, but we're hardening because the AST importer seems to be generating bad types - // on occasion. - return CompilerType(); + QualType qual_type(ClangUtil::GetQualType(type)); - return CompilerType(m_ast_context, copied_qual_type); -} + clang::ASTContext *ast = lldb_ast->getASTContext(); -clang::NamedDecl * -NameSearchContext::AddVarDecl(const CompilerType &type) -{ - assert (type && "Type for variable must be valid!"); + const bool isInlineSpecified = false; + const bool hasWrittenPrototype = true; + const bool isConstexprSpecified = false; - if (!type.IsValid()) - return NULL; + clang::DeclContext *context = const_cast<DeclContext *>(m_decl_context); - ClangASTContext* lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); - if (!lldb_ast) - return NULL; - - IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo(); + if (extern_c) { + context = LinkageSpecDecl::Create( + *ast, context, SourceLocation(), SourceLocation(), + clang::LinkageSpecDecl::LanguageIDs::lang_c, false); + } - clang::ASTContext *ast = lldb_ast->getASTContext(); + // Pass the identifier info for functions the decl_name is needed for + // operators + clang::DeclarationName decl_name = + m_decl_name.getNameKind() == DeclarationName::Identifier + ? m_decl_name.getAsIdentifierInfo() + : m_decl_name; - clang::NamedDecl *Decl = VarDecl::Create(*ast, const_cast<DeclContext *>(m_decl_context), SourceLocation(), - SourceLocation(), ii, ClangUtil::GetQualType(type), 0, SC_Static); - m_decls.push_back(Decl); + clang::FunctionDecl *func_decl = FunctionDecl::Create( + *ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type, + NULL, SC_Extern, isInlineSpecified, hasWrittenPrototype, + isConstexprSpecified); - return Decl; -} + // We have to do more than just synthesize the FunctionDecl. We have to + // synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do + // this, we raid the function's FunctionProtoType for types. -clang::NamedDecl * -NameSearchContext::AddFunDecl (const CompilerType &type, bool extern_c) -{ - assert (type && "Type for variable must be valid!"); - - if (!type.IsValid()) - return NULL; - - if (m_function_types.count(type)) - return NULL; - - ClangASTContext* lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); - if (!lldb_ast) - return NULL; - - m_function_types.insert(type); - - QualType qual_type(ClangUtil::GetQualType(type)); - - clang::ASTContext *ast = lldb_ast->getASTContext(); - - const bool isInlineSpecified = false; - const bool hasWrittenPrototype = true; - const bool isConstexprSpecified = false; - - clang::DeclContext *context = const_cast<DeclContext*>(m_decl_context); - - if (extern_c) { - context = LinkageSpecDecl::Create(*ast, - context, - SourceLocation(), - SourceLocation(), - clang::LinkageSpecDecl::LanguageIDs::lang_c, - false); - } + const FunctionProtoType *func_proto_type = + qual_type.getTypePtr()->getAs<FunctionProtoType>(); - // Pass the identifier info for functions the decl_name is needed for operators - clang::DeclarationName decl_name = m_decl_name.getNameKind() == DeclarationName::Identifier ? m_decl_name.getAsIdentifierInfo() : m_decl_name; - - clang::FunctionDecl *func_decl = FunctionDecl::Create (*ast, - context, - SourceLocation(), - SourceLocation(), - decl_name, - qual_type, - NULL, - SC_Extern, - isInlineSpecified, - hasWrittenPrototype, - isConstexprSpecified); - - // We have to do more than just synthesize the FunctionDecl. We have to - // synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do - // this, we raid the function's FunctionProtoType for types. - - const FunctionProtoType *func_proto_type = qual_type.getTypePtr()->getAs<FunctionProtoType>(); - - if (func_proto_type) - { - unsigned NumArgs = func_proto_type->getNumParams(); - unsigned ArgIndex; - - SmallVector<ParmVarDecl *, 5> parm_var_decls; - - for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) - { - QualType arg_qual_type (func_proto_type->getParamType(ArgIndex)); - - parm_var_decls.push_back(ParmVarDecl::Create (*ast, - const_cast<DeclContext*>(context), - SourceLocation(), - SourceLocation(), - NULL, - arg_qual_type, - NULL, - SC_Static, - NULL)); - } + if (func_proto_type) { + unsigned NumArgs = func_proto_type->getNumParams(); + unsigned ArgIndex; - func_decl->setParams(ArrayRef<ParmVarDecl*>(parm_var_decls)); - } - else - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + SmallVector<ParmVarDecl *, 5> parm_var_decls; - if (log) - log->Printf("Function type wasn't a FunctionProtoType"); + for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) { + QualType arg_qual_type(func_proto_type->getParamType(ArgIndex)); + + parm_var_decls.push_back(ParmVarDecl::Create( + *ast, const_cast<DeclContext *>(context), SourceLocation(), + SourceLocation(), NULL, arg_qual_type, NULL, SC_Static, NULL)); } - m_decls.push_back(func_decl); + func_decl->setParams(ArrayRef<ParmVarDecl *>(parm_var_decls)); + } else { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("Function type wasn't a FunctionProtoType"); + } + + m_decls.push_back(func_decl); - return func_decl; + return func_decl; } -clang::NamedDecl * -NameSearchContext::AddGenericFunDecl() -{ - FunctionProtoType::ExtProtoInfo proto_info; +clang::NamedDecl *NameSearchContext::AddGenericFunDecl() { + FunctionProtoType::ExtProtoInfo proto_info; - proto_info.Variadic = true; + proto_info.Variadic = true; - QualType generic_function_type(m_ast_source.m_ast_context->getFunctionType (m_ast_source.m_ast_context->UnknownAnyTy, // result - ArrayRef<QualType>(), // argument types - proto_info)); + QualType generic_function_type(m_ast_source.m_ast_context->getFunctionType( + m_ast_source.m_ast_context->UnknownAnyTy, // result + ArrayRef<QualType>(), // argument types + proto_info)); - return AddFunDecl(CompilerType (m_ast_source.m_ast_context, generic_function_type), true); + return AddFunDecl( + CompilerType(m_ast_source.m_ast_context, generic_function_type), true); } clang::NamedDecl * -NameSearchContext::AddTypeDecl(const CompilerType &clang_type) -{ - if (ClangUtil::IsClangType(clang_type)) - { - QualType qual_type = ClangUtil::GetQualType(clang_type); +NameSearchContext::AddTypeDecl(const CompilerType &clang_type) { + if (ClangUtil::IsClangType(clang_type)) { + QualType qual_type = ClangUtil::GetQualType(clang_type); - if (const TypedefType *typedef_type = llvm::dyn_cast<TypedefType>(qual_type)) - { - TypedefNameDecl *typedef_name_decl = typedef_type->getDecl(); + if (const TypedefType *typedef_type = + llvm::dyn_cast<TypedefType>(qual_type)) { + TypedefNameDecl *typedef_name_decl = typedef_type->getDecl(); - m_decls.push_back(typedef_name_decl); + m_decls.push_back(typedef_name_decl); - return (NamedDecl*)typedef_name_decl; - } - else if (const TagType *tag_type = qual_type->getAs<TagType>()) - { - TagDecl *tag_decl = tag_type->getDecl(); + return (NamedDecl *)typedef_name_decl; + } else if (const TagType *tag_type = qual_type->getAs<TagType>()) { + TagDecl *tag_decl = tag_type->getDecl(); - m_decls.push_back(tag_decl); + m_decls.push_back(tag_decl); - return tag_decl; - } - else if (const ObjCObjectType *objc_object_type = qual_type->getAs<ObjCObjectType>()) - { - ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface(); + return tag_decl; + } else if (const ObjCObjectType *objc_object_type = + qual_type->getAs<ObjCObjectType>()) { + ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface(); - m_decls.push_back((NamedDecl*)interface_decl); + m_decls.push_back((NamedDecl *)interface_decl); - return (NamedDecl*)interface_decl; - } + return (NamedDecl *)interface_decl; } - return NULL; + } + return NULL; } -void -NameSearchContext::AddLookupResult (clang::DeclContextLookupResult result) -{ - for (clang::NamedDecl *decl : result) - m_decls.push_back (decl); +void NameSearchContext::AddLookupResult(clang::DeclContextLookupResult result) { + for (clang::NamedDecl *decl : result) + m_decls.push_back(decl); } -void -NameSearchContext::AddNamedDecl (clang::NamedDecl *decl) -{ - m_decls.push_back (decl); +void NameSearchContext::AddNamedDecl(clang::NamedDecl *decl) { + m_decls.push_back(decl); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h index 13791d7e627..72ee50f5220 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -12,16 +12,16 @@ #include <set> -#include "clang/Basic/IdentifierTable.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Target.h" +#include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/SmallSet.h" namespace lldb_private { - + //---------------------------------------------------------------------- /// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h" /// @brief Provider for named objects defined in the debug info for Clang @@ -33,494 +33,479 @@ namespace lldb_private { /// to Clang for these names, consulting the ClangExpressionDeclMap to do /// the actual lookups. //---------------------------------------------------------------------- -class ClangASTSource : - public ClangExternalASTSourceCommon, - public ClangASTImporter::MapCompleter -{ +class ClangASTSource : public ClangExternalASTSourceCommon, + public ClangASTImporter::MapCompleter { public: - //------------------------------------------------------------------ - /// Constructor - /// - /// Initializes class variables. - /// - /// @param[in] declMap - /// A reference to the LLDB object that handles entity lookup. - //------------------------------------------------------------------ - ClangASTSource (const lldb::TargetSP &target) : - m_import_in_progress (false), - m_lookups_enabled (false), - m_target (target), - m_ast_context (NULL), - m_active_lexical_decls (), - m_active_lookups () - { - m_ast_importer_sp = m_target->GetClangASTImporter(); - } - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - ~ClangASTSource() override; - - //------------------------------------------------------------------ - /// Interface stubs. - //------------------------------------------------------------------ - clang::Decl *GetExternalDecl (uint32_t) override { return NULL; } - clang::Stmt *GetExternalDeclStmt (uint64_t) override { return NULL; } - clang::Selector GetExternalSelector (uint32_t) override { return clang::Selector(); } - uint32_t GetNumExternalSelectors () override { return 0; } - clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers (uint64_t Offset) override - { return NULL; } - void MaterializeVisibleDecls (const clang::DeclContext *DC) - { return; } - - void InstallASTContext (clang::ASTContext *ast_context) - { - m_ast_context = ast_context; - m_ast_importer_sp->InstallMapCompleter(ast_context, *this); + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] declMap + /// A reference to the LLDB object that handles entity lookup. + //------------------------------------------------------------------ + ClangASTSource(const lldb::TargetSP &target) + : m_import_in_progress(false), m_lookups_enabled(false), m_target(target), + m_ast_context(NULL), m_active_lexical_decls(), m_active_lookups() { + m_ast_importer_sp = m_target->GetClangASTImporter(); + } + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangASTSource() override; + + //------------------------------------------------------------------ + /// Interface stubs. + //------------------------------------------------------------------ + clang::Decl *GetExternalDecl(uint32_t) override { return NULL; } + clang::Stmt *GetExternalDeclStmt(uint64_t) override { return NULL; } + clang::Selector GetExternalSelector(uint32_t) override { + return clang::Selector(); + } + uint32_t GetNumExternalSelectors() override { return 0; } + clang::CXXBaseSpecifier * + GetExternalCXXBaseSpecifiers(uint64_t Offset) override { + return NULL; + } + void MaterializeVisibleDecls(const clang::DeclContext *DC) { return; } + + void InstallASTContext(clang::ASTContext *ast_context) { + m_ast_context = ast_context; + m_ast_importer_sp->InstallMapCompleter(ast_context, *this); + } + + // + // APIs for ExternalASTSource + // + + //------------------------------------------------------------------ + /// Look up all Decls that match a particular name. Only handles + /// Identifiers and DeclContexts that are either NamespaceDecls or + /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with + /// the result. + /// + /// The work for this function is done by + /// void FindExternalVisibleDecls (NameSearchContext &); + /// + /// @param[in] DC + /// The DeclContext to register the found Decls in. + /// + /// @param[in] Name + /// The name to find entries for. + /// + /// @return + /// Whatever SetExternalVisibleDeclsForName returns. + //------------------------------------------------------------------ + bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, + clang::DeclarationName Name) override; + + //------------------------------------------------------------------ + /// Enumerate all Decls in a given lexical context. + /// + /// @param[in] DC + /// The DeclContext being searched. + /// + /// @param[in] isKindWeWant + /// A callback function that returns true given the + /// DeclKinds of desired Decls, and false otherwise. + /// + /// @param[in] Decls + /// A vector that is filled in with matching Decls. + //------------------------------------------------------------------ + void FindExternalLexicalDecls( + const clang::DeclContext *DC, + llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, + llvm::SmallVectorImpl<clang::Decl *> &Decls) override; + + //------------------------------------------------------------------ + /// Specify the layout of the contents of a RecordDecl. + /// + /// @param[in] Record + /// The record (in the parser's AST context) that needs to be + /// laid out. + /// + /// @param[out] Size + /// The total size of the record in bits. + /// + /// @param[out] Alignment + /// The alignment of the record in bits. + /// + /// @param[in] FieldOffsets + /// A map that must be populated with pairs of the record's + /// fields (in the parser's AST context) and their offsets + /// (measured in bits). + /// + /// @param[in] BaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ concrete base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @param[in] VirtualBaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ virtual base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @return + /// True <=> the layout is valid. + //----------------------------------------------------------------- + bool layoutRecordType( + const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> + &BaseOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> + &VirtualBaseOffsets) override; + + //------------------------------------------------------------------ + /// Complete a TagDecl. + /// + /// @param[in] Tag + /// The Decl to be completed in place. + //------------------------------------------------------------------ + void CompleteType(clang::TagDecl *Tag) override; + + //------------------------------------------------------------------ + /// Complete an ObjCInterfaceDecl. + /// + /// @param[in] Class + /// The Decl to be completed in place. + //------------------------------------------------------------------ + void CompleteType(clang::ObjCInterfaceDecl *Class) override; + + //------------------------------------------------------------------ + /// Called on entering a translation unit. Tells Clang by calling + /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() + /// that this object has something to say about undefined names. + /// + /// @param[in] ASTConsumer + /// Unused. + //------------------------------------------------------------------ + void StartTranslationUnit(clang::ASTConsumer *Consumer) override; + + // + // APIs for NamespaceMapCompleter + // + + //------------------------------------------------------------------ + /// Look up the modules containing a given namespace and put the + /// appropriate entries in the namespace map. + /// + /// @param[in] namespace_map + /// The map to be completed. + /// + /// @param[in] name + /// The name of the namespace to be found. + /// + /// @param[in] parent_map + /// The map for the namespace's parent namespace, if there is + /// one. + //------------------------------------------------------------------ + void CompleteNamespaceMap( + ClangASTImporter::NamespaceMapSP &namespace_map, const ConstString &name, + ClangASTImporter::NamespaceMapSP &parent_map) const override; + + // + // Helper APIs + // + + clang::NamespaceDecl * + AddNamespace(NameSearchContext &context, + ClangASTImporter::NamespaceMapSP &namespace_decls); + + //------------------------------------------------------------------ + /// The worker function for FindExternalVisibleDeclsByName. + /// + /// @param[in] context + /// The NameSearchContext to use when filing results. + //------------------------------------------------------------------ + virtual void FindExternalVisibleDecls(NameSearchContext &context); + + void SetImportInProgress(bool import_in_progress) { + m_import_in_progress = import_in_progress; + } + bool GetImportInProgress() { return m_import_in_progress; } + + void SetLookupsEnabled(bool lookups_enabled) { + m_lookups_enabled = lookups_enabled; + } + bool GetLookupsEnabled() { return m_lookups_enabled; } + + //---------------------------------------------------------------------- + /// @class ClangASTSourceProxy ClangASTSource.h + /// "lldb/Expression/ClangASTSource.h" + /// @brief Proxy for ClangASTSource + /// + /// Clang AST contexts like to own their AST sources, so this is a + /// state-free proxy object. + //---------------------------------------------------------------------- + class ClangASTSourceProxy : public ClangExternalASTSourceCommon { + public: + ClangASTSourceProxy(ClangASTSource &original) : m_original(original) {} + + bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, + clang::DeclarationName Name) override { + return m_original.FindExternalVisibleDeclsByName(DC, Name); } - - // - // APIs for ExternalASTSource - // - - //------------------------------------------------------------------ - /// Look up all Decls that match a particular name. Only handles - /// Identifiers and DeclContexts that are either NamespaceDecls or - /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with - /// the result. - /// - /// The work for this function is done by - /// void FindExternalVisibleDecls (NameSearchContext &); - /// - /// @param[in] DC - /// The DeclContext to register the found Decls in. - /// - /// @param[in] Name - /// The name to find entries for. - /// - /// @return - /// Whatever SetExternalVisibleDeclsForName returns. - //------------------------------------------------------------------ - bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override; - - //------------------------------------------------------------------ - /// Enumerate all Decls in a given lexical context. - /// - /// @param[in] DC - /// The DeclContext being searched. - /// - /// @param[in] isKindWeWant - /// A callback function that returns true given the - /// DeclKinds of desired Decls, and false otherwise. - /// - /// @param[in] Decls - /// A vector that is filled in with matching Decls. - //------------------------------------------------------------------ + void FindExternalLexicalDecls( - const clang::DeclContext *DC, llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, - llvm::SmallVectorImpl<clang::Decl *> &Decls) override; - - //------------------------------------------------------------------ - /// Specify the layout of the contents of a RecordDecl. - /// - /// @param[in] Record - /// The record (in the parser's AST context) that needs to be - /// laid out. - /// - /// @param[out] Size - /// The total size of the record in bits. - /// - /// @param[out] Alignment - /// The alignment of the record in bits. - /// - /// @param[in] FieldOffsets - /// A map that must be populated with pairs of the record's - /// fields (in the parser's AST context) and their offsets - /// (measured in bits). - /// - /// @param[in] BaseOffsets - /// A map that must be populated with pairs of the record's - /// C++ concrete base classes (in the parser's AST context, - /// and only if the record is a CXXRecordDecl and has base - /// classes) and their offsets (measured in bytes). - /// - /// @param[in] VirtualBaseOffsets - /// A map that must be populated with pairs of the record's - /// C++ virtual base classes (in the parser's AST context, - /// and only if the record is a CXXRecordDecl and has base - /// classes) and their offsets (measured in bytes). - /// - /// @return - /// True <=> the layout is valid. - //----------------------------------------------------------------- - bool layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, - llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override; - - //------------------------------------------------------------------ - /// Complete a TagDecl. - /// - /// @param[in] Tag - /// The Decl to be completed in place. - //------------------------------------------------------------------ - void CompleteType(clang::TagDecl *Tag) override; - - //------------------------------------------------------------------ - /// Complete an ObjCInterfaceDecl. - /// - /// @param[in] Class - /// The Decl to be completed in place. - //------------------------------------------------------------------ - void CompleteType(clang::ObjCInterfaceDecl *Class) override; - - //------------------------------------------------------------------ - /// Called on entering a translation unit. Tells Clang by calling - /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() - /// that this object has something to say about undefined names. - /// - /// @param[in] ASTConsumer - /// Unused. - //------------------------------------------------------------------ - void StartTranslationUnit(clang::ASTConsumer *Consumer) override; - - // - // APIs for NamespaceMapCompleter - // - - //------------------------------------------------------------------ - /// Look up the modules containing a given namespace and put the - /// appropriate entries in the namespace map. - /// - /// @param[in] namespace_map - /// The map to be completed. - /// - /// @param[in] name - /// The name of the namespace to be found. - /// - /// @param[in] parent_map - /// The map for the namespace's parent namespace, if there is - /// one. - //------------------------------------------------------------------ - void CompleteNamespaceMap(ClangASTImporter::NamespaceMapSP &namespace_map, const ConstString &name, - ClangASTImporter::NamespaceMapSP &parent_map) const override; - - // - // Helper APIs - // - - clang::NamespaceDecl * - AddNamespace (NameSearchContext &context, - ClangASTImporter::NamespaceMapSP &namespace_decls); - - //------------------------------------------------------------------ - /// The worker function for FindExternalVisibleDeclsByName. - /// - /// @param[in] context - /// The NameSearchContext to use when filing results. - //------------------------------------------------------------------ - virtual void FindExternalVisibleDecls (NameSearchContext &context); - - void SetImportInProgress (bool import_in_progress) { m_import_in_progress = import_in_progress; } - bool GetImportInProgress () { return m_import_in_progress; } - - void SetLookupsEnabled (bool lookups_enabled) { m_lookups_enabled = lookups_enabled; } - bool GetLookupsEnabled () { return m_lookups_enabled; } - - //---------------------------------------------------------------------- - /// @class ClangASTSourceProxy ClangASTSource.h "lldb/Expression/ClangASTSource.h" - /// @brief Proxy for ClangASTSource - /// - /// Clang AST contexts like to own their AST sources, so this is a - /// state-free proxy object. - //---------------------------------------------------------------------- - class ClangASTSourceProxy : public ClangExternalASTSourceCommon - { - public: - ClangASTSourceProxy (ClangASTSource &original) : - m_original(original) - { - } - - bool - FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override - { - return m_original.FindExternalVisibleDeclsByName(DC, Name); - } - - void - FindExternalLexicalDecls(const clang::DeclContext *DC, - llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, - llvm::SmallVectorImpl<clang::Decl *> &Decls) override - { - return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls); - } - - void - CompleteType(clang::TagDecl *Tag) override - { - return m_original.CompleteType(Tag); - } - - void - CompleteType(clang::ObjCInterfaceDecl *Class) override - { - return m_original.CompleteType(Class); - } - - bool - layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, - llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override - { - return m_original.layoutRecordType(Record, - Size, - Alignment, - FieldOffsets, - BaseOffsets, - VirtualBaseOffsets); - } - - void - StartTranslationUnit(clang::ASTConsumer *Consumer) override - { - return m_original.StartTranslationUnit(Consumer); - } - - ClangASTMetadata * - GetMetadata(const void * object) - { - return m_original.GetMetadata(object); - } - - void - SetMetadata(const void * object, ClangASTMetadata &metadata) - { - return m_original.SetMetadata(object, metadata); - } - - bool - HasMetadata(const void * object) - { - return m_original.HasMetadata(object); - } - private: - ClangASTSource &m_original; - }; - - clang::ExternalASTSource *CreateProxy() - { - return new ClangASTSourceProxy(*this); + const clang::DeclContext *DC, + llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, + llvm::SmallVectorImpl<clang::Decl *> &Decls) override { + return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls); + } + + void CompleteType(clang::TagDecl *Tag) override { + return m_original.CompleteType(Tag); + } + + void CompleteType(clang::ObjCInterfaceDecl *Class) override { + return m_original.CompleteType(Class); } - + + bool layoutRecordType( + const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> + &BaseOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> + &VirtualBaseOffsets) override { + return m_original.layoutRecordType(Record, Size, Alignment, FieldOffsets, + BaseOffsets, VirtualBaseOffsets); + } + + void StartTranslationUnit(clang::ASTConsumer *Consumer) override { + return m_original.StartTranslationUnit(Consumer); + } + + ClangASTMetadata *GetMetadata(const void *object) { + return m_original.GetMetadata(object); + } + + void SetMetadata(const void *object, ClangASTMetadata &metadata) { + return m_original.SetMetadata(object, metadata); + } + + bool HasMetadata(const void *object) { + return m_original.HasMetadata(object); + } + + private: + ClangASTSource &m_original; + }; + + clang::ExternalASTSource *CreateProxy() { + return new ClangASTSourceProxy(*this); + } + protected: - //------------------------------------------------------------------ - /// Look for the complete version of an Objective-C interface, and - /// return it if found. - /// - /// @param[in] interface_decl - /// An ObjCInterfaceDecl that may not be the complete one. - /// - /// @return - /// NULL if the complete interface couldn't be found; - /// the complete interface otherwise. - //------------------------------------------------------------------ - clang::ObjCInterfaceDecl * - GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl); - - //------------------------------------------------------------------ - /// Find all entities matching a given name in a given module, - /// using a NameSearchContext to make Decls for them. - /// - /// @param[in] context - /// The NameSearchContext that can construct Decls for this name. - /// - /// @param[in] module - /// If non-NULL, the module to query. - /// - /// @param[in] namespace_decl - /// If valid and module is non-NULL, the parent namespace. - /// - /// @param[in] current_id - /// The ID for the current FindExternalVisibleDecls invocation, - /// for logging purposes. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - void - FindExternalVisibleDecls (NameSearchContext &context, - lldb::ModuleSP module, - CompilerDeclContext &namespace_decl, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Find all Objective-C methods matching a given selector. - /// - /// @param[in] context - /// The NameSearchContext that can construct Decls for this name. - /// Its m_decl_name contains the selector and its m_decl_context - /// is the containing object. - //------------------------------------------------------------------ - void - FindObjCMethodDecls (NameSearchContext &context); - - //------------------------------------------------------------------ - /// Find all Objective-C properties and ivars with a given name. - /// - /// @param[in] context - /// The NameSearchContext that can construct Decls for this name. - /// Its m_decl_name contains the name and its m_decl_context - /// is the containing object. - //------------------------------------------------------------------ - void - FindObjCPropertyAndIvarDecls (NameSearchContext &context); - - //------------------------------------------------------------------ - /// A wrapper for ClangASTContext::CopyType that sets a flag that - /// indicates that we should not respond to queries during import. - /// - /// @param[in] dest_context - /// The target AST context, typically the parser's AST context. - /// - /// @param[in] source_context - /// The source AST context, typically the AST context of whatever - /// symbol file the type was found in. - /// - /// @param[in] src_type - /// The source type. - /// - /// @return - /// The imported type. - //------------------------------------------------------------------ - CompilerType - GuardedCopyType (const CompilerType &src_type); - - friend struct NameSearchContext; - - bool m_import_in_progress; - bool m_lookups_enabled; - - const lldb::TargetSP m_target; ///< The target to use in finding variables and types. - clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. - lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer. - std::set<const clang::Decl *> m_active_lexical_decls; - std::set<const char *> m_active_lookups; + //------------------------------------------------------------------ + /// Look for the complete version of an Objective-C interface, and + /// return it if found. + /// + /// @param[in] interface_decl + /// An ObjCInterfaceDecl that may not be the complete one. + /// + /// @return + /// NULL if the complete interface couldn't be found; + /// the complete interface otherwise. + //------------------------------------------------------------------ + clang::ObjCInterfaceDecl * + GetCompleteObjCInterface(clang::ObjCInterfaceDecl *interface_decl); + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// @param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void FindExternalVisibleDecls(NameSearchContext &context, + lldb::ModuleSP module, + CompilerDeclContext &namespace_decl, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Find all Objective-C methods matching a given selector. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the selector and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void FindObjCMethodDecls(NameSearchContext &context); + + //------------------------------------------------------------------ + /// Find all Objective-C properties and ivars with a given name. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the name and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void FindObjCPropertyAndIvarDecls(NameSearchContext &context); + + //------------------------------------------------------------------ + /// A wrapper for ClangASTContext::CopyType that sets a flag that + /// indicates that we should not respond to queries during import. + /// + /// @param[in] dest_context + /// The target AST context, typically the parser's AST context. + /// + /// @param[in] source_context + /// The source AST context, typically the AST context of whatever + /// symbol file the type was found in. + /// + /// @param[in] src_type + /// The source type. + /// + /// @return + /// The imported type. + //------------------------------------------------------------------ + CompilerType GuardedCopyType(const CompilerType &src_type); + + friend struct NameSearchContext; + + bool m_import_in_progress; + bool m_lookups_enabled; + + const lldb::TargetSP + m_target; ///< The target to use in finding variables and types. + clang::ASTContext + *m_ast_context; ///< The AST context requests are coming in for. + lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer. + std::set<const clang::Decl *> m_active_lexical_decls; + std::set<const char *> m_active_lookups; }; //---------------------------------------------------------------------- /// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h" /// @brief Container for all objects relevant to a single name lookup -/// +/// /// LLDB needs to create Decls for entities it finds. This class communicates /// what name is being searched for and provides helper functions to construct /// Decls given appropriate type information. //---------------------------------------------------------------------- struct NameSearchContext { - ClangASTSource &m_ast_source; ///< The AST source making the request - llvm::SmallVectorImpl<clang::NamedDecl*> &m_decls; ///< The list of declarations already constructed - ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all namespaces found for this request back to their modules - const clang::DeclarationName &m_decl_name; ///< The name being looked for - const clang::DeclContext *m_decl_context; ///< The DeclContext to put declarations into - llvm::SmallSet <CompilerType, 5> m_function_types; ///< All the types of functions that have been reported, so we don't report conflicts - - struct { - bool variable : 1; - bool function_with_type_info : 1; - bool function : 1; - bool local_vars_nsp : 1; - bool type : 1; - } m_found; - - //------------------------------------------------------------------ - /// Constructor - /// - /// Initializes class variables. - /// - /// @param[in] astSource - /// A reference to the AST source making a request. - /// - /// @param[in] decls - /// A reference to a list into which new Decls will be placed. This - /// list is typically empty when the function is called. - /// - /// @param[in] name - /// The name being searched for (always an Identifier). - /// - /// @param[in] dc - /// The DeclContext to register Decls in. - //------------------------------------------------------------------ - NameSearchContext (ClangASTSource &astSource, - llvm::SmallVectorImpl<clang::NamedDecl*> &decls, - clang::DeclarationName &name, - const clang::DeclContext *dc) : - m_ast_source(astSource), - m_decls(decls), - m_decl_name(name), - m_decl_context(dc) - { - memset(&m_found, 0, sizeof(m_found)); - } - - //------------------------------------------------------------------ - /// Create a VarDecl with the name being searched for and the provided - /// type and register it in the right places. - /// - /// @param[in] type - /// The opaque QualType for the VarDecl being registered. - //------------------------------------------------------------------ - clang::NamedDecl *AddVarDecl(const CompilerType &type); - - //------------------------------------------------------------------ - /// Create a FunDecl with the name being searched for and the provided - /// type and register it in the right places. - /// - /// @param[in] type - /// The opaque QualType for the FunDecl being registered. - /// - /// @param[in] extern_c - /// If true, build an extern "C" linkage specification for this. - //------------------------------------------------------------------ - clang::NamedDecl *AddFunDecl(const CompilerType &type, - bool extern_c = false); - - //------------------------------------------------------------------ - /// Create a FunDecl with the name being searched for and generic - /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the - /// right places. - //------------------------------------------------------------------ - clang::NamedDecl *AddGenericFunDecl(); - - //------------------------------------------------------------------ - /// Create a TypeDecl with the name being searched for and the provided - /// type and register it in the right places. - /// - /// @param[in] compiler_type - /// The opaque QualType for the TypeDecl being registered. - //------------------------------------------------------------------ - clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type); - - - //------------------------------------------------------------------ - /// Add Decls from the provided DeclContextLookupResult to the list - /// of results. - /// - /// @param[in] result - /// The DeclContextLookupResult, usually returned as the result - /// of querying a DeclContext. - //------------------------------------------------------------------ - void AddLookupResult (clang::DeclContextLookupResult result); - - //------------------------------------------------------------------ - /// Add a NamedDecl to the list of results. - /// - /// @param[in] decl - /// The NamedDecl, usually returned as the result - /// of querying a DeclContext. - //------------------------------------------------------------------ - void AddNamedDecl (clang::NamedDecl *decl); + ClangASTSource &m_ast_source; ///< The AST source making the request + llvm::SmallVectorImpl<clang::NamedDecl *> + &m_decls; ///< The list of declarations already constructed + ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all + ///namespaces found for this + ///request back to their + ///modules + const clang::DeclarationName &m_decl_name; ///< The name being looked for + const clang::DeclContext + *m_decl_context; ///< The DeclContext to put declarations into + llvm::SmallSet<CompilerType, 5> m_function_types; ///< All the types of + ///functions that have been + ///reported, so we don't + ///report conflicts + + struct { + bool variable : 1; + bool function_with_type_info : 1; + bool function : 1; + bool local_vars_nsp : 1; + bool type : 1; + } m_found; + + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] astSource + /// A reference to the AST source making a request. + /// + /// @param[in] decls + /// A reference to a list into which new Decls will be placed. This + /// list is typically empty when the function is called. + /// + /// @param[in] name + /// The name being searched for (always an Identifier). + /// + /// @param[in] dc + /// The DeclContext to register Decls in. + //------------------------------------------------------------------ + NameSearchContext(ClangASTSource &astSource, + llvm::SmallVectorImpl<clang::NamedDecl *> &decls, + clang::DeclarationName &name, const clang::DeclContext *dc) + : m_ast_source(astSource), m_decls(decls), m_decl_name(name), + m_decl_context(dc) { + memset(&m_found, 0, sizeof(m_found)); + } + + //------------------------------------------------------------------ + /// Create a VarDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the VarDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddVarDecl(const CompilerType &type); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the FunDecl being registered. + /// + /// @param[in] extern_c + /// If true, build an extern "C" linkage specification for this. + //------------------------------------------------------------------ + clang::NamedDecl *AddFunDecl(const CompilerType &type, bool extern_c = false); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and generic + /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the + /// right places. + //------------------------------------------------------------------ + clang::NamedDecl *AddGenericFunDecl(); + + //------------------------------------------------------------------ + /// Create a TypeDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] compiler_type + /// The opaque QualType for the TypeDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type); + + //------------------------------------------------------------------ + /// Add Decls from the provided DeclContextLookupResult to the list + /// of results. + /// + /// @param[in] result + /// The DeclContextLookupResult, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddLookupResult(clang::DeclContextLookupResult result); + + //------------------------------------------------------------------ + /// Add a NamedDecl to the list of results. + /// + /// @param[in] decl + /// The NamedDecl, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddNamedDecl(clang::NamedDecl *decl); }; } // namespace lldb_private diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h index 8273bca105c..9ea4e3aa7da 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h @@ -19,42 +19,32 @@ #include "lldb/Expression/DiagnosticManager.h" -namespace lldb_private -{ +namespace lldb_private { - -class ClangDiagnostic : public Diagnostic -{ +class ClangDiagnostic : public Diagnostic { public: - typedef std::vector<clang::FixItHint> FixItList; - - static inline bool classof(const ClangDiagnostic *) { return true; } - static inline bool classof(const Diagnostic *diag) { - return diag->getKind() == eDiagnosticOriginClang; - } - - ClangDiagnostic(const char *message, DiagnosticSeverity severity, uint32_t compiler_id) : - Diagnostic(message, severity, eDiagnosticOriginClang, compiler_id) - { - } - - virtual ~ClangDiagnostic() = default; - - bool HasFixIts () const override { return !m_fixit_vec.empty(); } - - void - AddFixitHint (const clang::FixItHint &fixit) - { - m_fixit_vec.push_back(fixit); - } - - const FixItList & - FixIts() const - { - return m_fixit_vec; - } - FixItList m_fixit_vec; + typedef std::vector<clang::FixItHint> FixItList; + + static inline bool classof(const ClangDiagnostic *) { return true; } + static inline bool classof(const Diagnostic *diag) { + return diag->getKind() == eDiagnosticOriginClang; + } + + ClangDiagnostic(const char *message, DiagnosticSeverity severity, + uint32_t compiler_id) + : Diagnostic(message, severity, eDiagnosticOriginClang, compiler_id) {} + + virtual ~ClangDiagnostic() = default; + + bool HasFixIts() const override { return !m_fixit_vec.empty(); } + + void AddFixitHint(const clang::FixItHint &fixit) { + m_fixit_vec.push_back(fixit); + } + + const FixItList &FixIts() const { return m_fixit_vec; } + FixItList m_fixit_vec; }; -} // namespace lldb_private +} // namespace lldb_private #endif /* lldb_ClangDiagnostic_h */ diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index a0ea8ae730f..3fa78f01f51 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -14,11 +14,6 @@ #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Decl.h" -#include "lldb/lldb-private.h" #include "lldb/Core/Address.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" @@ -30,9 +25,9 @@ #include "lldb/Expression/Materializer.h" #include "lldb/Host/Endian.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" -#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" @@ -50,6 +45,11 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/lldb-private.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclarationName.h" #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" @@ -57,1586 +57,1501 @@ using namespace lldb; using namespace lldb_private; using namespace clang; -namespace -{ - const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars"; +namespace { +const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars"; } // anonymous namespace -ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory, - Materializer::PersistentVariableDelegate *result_delegate, - ExecutionContext &exe_ctx) : - ClangASTSource (exe_ctx.GetTargetSP()), - m_found_entities (), - m_struct_members (), - m_keep_result_in_memory (keep_result_in_memory), - m_result_delegate (result_delegate), - m_parser_vars (), - m_struct_vars () -{ - EnableStructVars(); +ClangExpressionDeclMap::ClangExpressionDeclMap( + bool keep_result_in_memory, + Materializer::PersistentVariableDelegate *result_delegate, + ExecutionContext &exe_ctx) + : ClangASTSource(exe_ctx.GetTargetSP()), m_found_entities(), + m_struct_members(), m_keep_result_in_memory(keep_result_in_memory), + m_result_delegate(result_delegate), m_parser_vars(), m_struct_vars() { + EnableStructVars(); } -ClangExpressionDeclMap::~ClangExpressionDeclMap() -{ - // Note: The model is now that the parser's AST context and all associated - // data does not vanish until the expression has been executed. This means - // that valuable lookup data (like namespaces) doesn't vanish, but +ClangExpressionDeclMap::~ClangExpressionDeclMap() { + // Note: The model is now that the parser's AST context and all associated + // data does not vanish until the expression has been executed. This means + // that valuable lookup data (like namespaces) doesn't vanish, but - DidParse(); - DisableStructVars(); + DidParse(); + DisableStructVars(); } -bool -ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx, - Materializer *materializer) -{ - ClangASTMetrics::ClearLocalCounters(); - - EnableParserVars(); - m_parser_vars->m_exe_ctx = exe_ctx; - - Target *target = exe_ctx.GetTargetPtr(); - if (exe_ctx.GetFramePtr()) - m_parser_vars->m_sym_ctx = exe_ctx.GetFramePtr()->GetSymbolContext(lldb::eSymbolContextEverything); - else if (exe_ctx.GetThreadPtr() && exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)) - m_parser_vars->m_sym_ctx = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)->GetSymbolContext(lldb::eSymbolContextEverything); - else if (exe_ctx.GetProcessPtr()) - { - m_parser_vars->m_sym_ctx.Clear(true); - m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); - } - else if (target) - { - m_parser_vars->m_sym_ctx.Clear(true); - m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); - } - - if (target) - { - m_parser_vars->m_persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(eLanguageTypeC)); - - if (!target->GetScratchClangASTContext()) - return false; - } - - m_parser_vars->m_target_info = GetTargetInfo(); - m_parser_vars->m_materializer = materializer; - - return true; +bool ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx, + Materializer *materializer) { + ClangASTMetrics::ClearLocalCounters(); + + EnableParserVars(); + m_parser_vars->m_exe_ctx = exe_ctx; + + Target *target = exe_ctx.GetTargetPtr(); + if (exe_ctx.GetFramePtr()) + m_parser_vars->m_sym_ctx = + exe_ctx.GetFramePtr()->GetSymbolContext(lldb::eSymbolContextEverything); + else if (exe_ctx.GetThreadPtr() && + exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)) + m_parser_vars->m_sym_ctx = + exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)->GetSymbolContext( + lldb::eSymbolContextEverything); + else if (exe_ctx.GetProcessPtr()) { + m_parser_vars->m_sym_ctx.Clear(true); + m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); + } else if (target) { + m_parser_vars->m_sym_ctx.Clear(true); + m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); + } + + if (target) { + m_parser_vars->m_persistent_vars = llvm::cast<ClangPersistentVariables>( + target->GetPersistentExpressionStateForLanguage(eLanguageTypeC)); + + if (!target->GetScratchClangASTContext()) + return false; + } + + m_parser_vars->m_target_info = GetTargetInfo(); + m_parser_vars->m_materializer = materializer; + + return true; } -void -ClangExpressionDeclMap::InstallCodeGenerator (clang::ASTConsumer *code_gen) -{ - assert(m_parser_vars); - m_parser_vars->m_code_gen = code_gen; +void ClangExpressionDeclMap::InstallCodeGenerator( + clang::ASTConsumer *code_gen) { + assert(m_parser_vars); + m_parser_vars->m_code_gen = code_gen; } -void -ClangExpressionDeclMap::DidParse() -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +void ClangExpressionDeclMap::DidParse() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - ClangASTMetrics::DumpCounters(log); - - if (m_parser_vars.get()) - { - for (size_t entity_index = 0, num_entities = m_found_entities.GetSize(); - entity_index < num_entities; - ++entity_index) - { - ExpressionVariableSP var_sp(m_found_entities.GetVariableAtIndex(entity_index)); - if (var_sp) - llvm::cast<ClangExpressionVariable>(var_sp.get())->DisableParserVars(GetParserID()); - } + if (log) + ClangASTMetrics::DumpCounters(log); - for (size_t pvar_index = 0, num_pvars = m_parser_vars->m_persistent_vars->GetSize(); - pvar_index < num_pvars; - ++pvar_index) - { - ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index)); - if (ClangExpressionVariable *clang_var = llvm::dyn_cast<ClangExpressionVariable>(pvar_sp.get())) - clang_var->DisableParserVars(GetParserID()); - } + if (m_parser_vars.get()) { + for (size_t entity_index = 0, num_entities = m_found_entities.GetSize(); + entity_index < num_entities; ++entity_index) { + ExpressionVariableSP var_sp( + m_found_entities.GetVariableAtIndex(entity_index)); + if (var_sp) + llvm::cast<ClangExpressionVariable>(var_sp.get()) + ->DisableParserVars(GetParserID()); + } - DisableParserVars(); + for (size_t pvar_index = 0, + num_pvars = m_parser_vars->m_persistent_vars->GetSize(); + pvar_index < num_pvars; ++pvar_index) { + ExpressionVariableSP pvar_sp( + m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index)); + if (ClangExpressionVariable *clang_var = + llvm::dyn_cast<ClangExpressionVariable>(pvar_sp.get())) + clang_var->DisableParserVars(GetParserID()); } + + DisableParserVars(); + } } // Interface for IRForTarget -ClangExpressionDeclMap::TargetInfo -ClangExpressionDeclMap::GetTargetInfo() -{ - assert (m_parser_vars.get()); +ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() { + assert(m_parser_vars.get()); - TargetInfo ret; + TargetInfo ret; - ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; - Process *process = exe_ctx.GetProcessPtr(); - if (process) - { - ret.byte_order = process->GetByteOrder(); - ret.address_byte_size = process->GetAddressByteSize(); - } - else - { - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - ret.byte_order = target->GetArchitecture().GetByteOrder(); - ret.address_byte_size = target->GetArchitecture().GetAddressByteSize(); - } + Process *process = exe_ctx.GetProcessPtr(); + if (process) { + ret.byte_order = process->GetByteOrder(); + ret.address_byte_size = process->GetAddressByteSize(); + } else { + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + ret.byte_order = target->GetArchitecture().GetByteOrder(); + ret.address_byte_size = target->GetArchitecture().GetAddressByteSize(); } + } - return ret; + return ret; } -bool -ClangExpressionDeclMap::AddPersistentVariable -( - const NamedDecl *decl, - const ConstString &name, - TypeFromParser parser_type, - bool is_result, - bool is_lvalue -) -{ - assert (m_parser_vars.get()); - - ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(parser_type.GetTypeSystem()); - if (ast == nullptr) - return false; +bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, + const ConstString &name, + TypeFromParser parser_type, + bool is_result, + bool is_lvalue) { + assert(m_parser_vars.get()); - if (m_parser_vars->m_materializer && is_result) - { - Error err; + ClangASTContext *ast = + llvm::dyn_cast_or_null<ClangASTContext>(parser_type.GetTypeSystem()); + if (ast == nullptr) + return false; - ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; - Target *target = exe_ctx.GetTargetPtr(); - if (target == nullptr) - return false; + if (m_parser_vars->m_materializer && is_result) { + Error err; - ClangASTContext *context(target->GetScratchClangASTContext()); + ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + Target *target = exe_ctx.GetTargetPtr(); + if (target == nullptr) + return false; - TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(), - ast->getASTContext(), - parser_type.GetOpaqueQualType()), - context); - - uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type, - is_lvalue, - m_keep_result_in_memory, - m_result_delegate, - err); + ClangASTContext *context(target->GetScratchClangASTContext()); - ClangExpressionVariable *var = new ClangExpressionVariable(exe_ctx.GetBestExecutionContextScope(), - name, - user_type, - m_parser_vars->m_target_info.byte_order, - m_parser_vars->m_target_info.address_byte_size); + TypeFromUser user_type(m_ast_importer_sp->DeportType( + context->getASTContext(), ast->getASTContext(), + parser_type.GetOpaqueQualType()), + context); - m_found_entities.AddNewlyConstructedVariable(var); - - var->EnableParserVars(GetParserID()); + uint32_t offset = m_parser_vars->m_materializer->AddResultVariable( + user_type, is_lvalue, m_keep_result_in_memory, m_result_delegate, err); - ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID()); + ClangExpressionVariable *var = new ClangExpressionVariable( + exe_ctx.GetBestExecutionContextScope(), name, user_type, + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size); - parser_vars->m_named_decl = decl; - parser_vars->m_parser_type = parser_type; + m_found_entities.AddNewlyConstructedVariable(var); - var->EnableJITVars(GetParserID()); + var->EnableParserVars(GetParserID()); - ClangExpressionVariable::JITVars *jit_vars = var->GetJITVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = + var->GetParserVars(GetParserID()); - jit_vars->m_offset = offset; + parser_vars->m_named_decl = decl; + parser_vars->m_parser_type = parser_type; - return true; - } + var->EnableJITVars(GetParserID()); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; - Target *target = exe_ctx.GetTargetPtr(); - if (target == NULL) - return false; + ClangExpressionVariable::JITVars *jit_vars = var->GetJITVars(GetParserID()); - ClangASTContext *context(target->GetScratchClangASTContext()); + jit_vars->m_offset = offset; - TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(), - ast->getASTContext(), - parser_type.GetOpaqueQualType()), - context); + return true; + } - if (!user_type.GetOpaqueQualType()) - { - if (log) - log->Printf("Persistent variable's type wasn't copied successfully"); - return false; - } + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + Target *target = exe_ctx.GetTargetPtr(); + if (target == NULL) + return false; - if (!m_parser_vars->m_target_info.IsValid()) - return false; + ClangASTContext *context(target->GetScratchClangASTContext()); - ClangExpressionVariable *var = llvm::cast<ClangExpressionVariable>(m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx.GetBestExecutionContextScope (), - name, - user_type, - m_parser_vars->m_target_info.byte_order, - m_parser_vars->m_target_info.address_byte_size).get()); + TypeFromUser user_type(m_ast_importer_sp->DeportType( + context->getASTContext(), ast->getASTContext(), + parser_type.GetOpaqueQualType()), + context); - if (!var) - return false; + if (!user_type.GetOpaqueQualType()) { + if (log) + log->Printf("Persistent variable's type wasn't copied successfully"); + return false; + } - var->m_frozen_sp->SetHasCompleteType(); + if (!m_parser_vars->m_target_info.IsValid()) + return false; - if (is_result) - var->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry; - else - var->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist + ClangExpressionVariable *var = llvm::cast<ClangExpressionVariable>( + m_parser_vars->m_persistent_vars + ->CreatePersistentVariable( + exe_ctx.GetBestExecutionContextScope(), name, user_type, + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size) + .get()); - if (is_lvalue) - { - var->m_flags |= ClangExpressionVariable::EVIsProgramReference; - } - else - { - var->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; - var->m_flags |= ClangExpressionVariable::EVNeedsAllocation; - } + if (!var) + return false; - if (m_keep_result_in_memory) - { - var->m_flags |= ClangExpressionVariable::EVKeepInTarget; - } + var->m_frozen_sp->SetHasCompleteType(); - if (log) - log->Printf("Created persistent variable with flags 0x%hx", var->m_flags); + if (is_result) + var->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry; + else + var->m_flags |= + ClangExpressionVariable::EVKeepInTarget; // explicitly-declared + // persistent variables should + // persist - var->EnableParserVars(GetParserID()); + if (is_lvalue) { + var->m_flags |= ClangExpressionVariable::EVIsProgramReference; + } else { + var->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; + var->m_flags |= ClangExpressionVariable::EVNeedsAllocation; + } - ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID()); + if (m_keep_result_in_memory) { + var->m_flags |= ClangExpressionVariable::EVKeepInTarget; + } - parser_vars->m_named_decl = decl; - parser_vars->m_parser_type = parser_type; + if (log) + log->Printf("Created persistent variable with flags 0x%hx", var->m_flags); - return true; -} + var->EnableParserVars(GetParserID()); -bool -ClangExpressionDeclMap::AddValueToStruct -( - const NamedDecl *decl, - const ConstString &name, - llvm::Value *value, - size_t size, - lldb::offset_t alignment -) -{ - assert (m_struct_vars.get()); - assert (m_parser_vars.get()); + ClangExpressionVariable::ParserVars *parser_vars = + var->GetParserVars(GetParserID()); - bool is_persistent_variable = false; + parser_vars->m_named_decl = decl; + parser_vars->m_parser_type = parser_type; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + return true; +} - m_struct_vars->m_struct_laid_out = false; +bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, + const ConstString &name, + llvm::Value *value, size_t size, + lldb::offset_t alignment) { + assert(m_struct_vars.get()); + assert(m_parser_vars.get()); - if (ClangExpressionVariable::FindVariableInList(m_struct_members, decl, GetParserID())) - return true; + bool is_persistent_variable = false; - ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID())); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (!var) - { - var = ClangExpressionVariable::FindVariableInList(*m_parser_vars->m_persistent_vars, decl, GetParserID()); - is_persistent_variable = true; - } + m_struct_vars->m_struct_laid_out = false; - if (!var) - return false; + if (ClangExpressionVariable::FindVariableInList(m_struct_members, decl, + GetParserID())) + return true; - if (log) - log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure", - static_cast<const void*>(decl), name.GetCString(), - var->GetName().GetCString()); + ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList( + m_found_entities, decl, GetParserID())); - // We know entity->m_parser_vars is valid because we used a parser variable - // to find it + if (!var) { + var = ClangExpressionVariable::FindVariableInList( + *m_parser_vars->m_persistent_vars, decl, GetParserID()); + is_persistent_variable = true; + } - ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(var)->GetParserVars(GetParserID()); + if (!var) + return false; - parser_vars->m_llvm_value = value; + if (log) + log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure", + static_cast<const void *>(decl), name.GetCString(), + var->GetName().GetCString()); - if (ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID())) - { - // We already laid this out; do not touch + // We know entity->m_parser_vars is valid because we used a parser variable + // to find it - if (log) - log->Printf("Already placed at 0x%llx", (unsigned long long)jit_vars->m_offset); - } + ClangExpressionVariable::ParserVars *parser_vars = + llvm::cast<ClangExpressionVariable>(var)->GetParserVars(GetParserID()); - llvm::cast<ClangExpressionVariable>(var)->EnableJITVars(GetParserID()); + parser_vars->m_llvm_value = value; - ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID()); + if (ClangExpressionVariable::JITVars *jit_vars = + llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID())) { + // We already laid this out; do not touch - jit_vars->m_alignment = alignment; - jit_vars->m_size = size; + if (log) + log->Printf("Already placed at 0x%llx", + (unsigned long long)jit_vars->m_offset); + } - m_struct_members.AddVariable(var->shared_from_this()); + llvm::cast<ClangExpressionVariable>(var)->EnableJITVars(GetParserID()); - if (m_parser_vars->m_materializer) - { - uint32_t offset = 0; + ClangExpressionVariable::JITVars *jit_vars = + llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID()); - Error err; + jit_vars->m_alignment = alignment; + jit_vars->m_size = size; - if (is_persistent_variable) - { - ExpressionVariableSP var_sp(var->shared_from_this()); - offset = m_parser_vars->m_materializer->AddPersistentVariable(var_sp, nullptr, err); - } - else - { - if (const lldb_private::Symbol *sym = parser_vars->m_lldb_sym) - offset = m_parser_vars->m_materializer->AddSymbol(*sym, err); - else if (const RegisterInfo *reg_info = var->GetRegisterInfo()) - offset = m_parser_vars->m_materializer->AddRegister(*reg_info, err); - else if (parser_vars->m_lldb_var) - offset = m_parser_vars->m_materializer->AddVariable(parser_vars->m_lldb_var, err); - } + m_struct_members.AddVariable(var->shared_from_this()); - if (!err.Success()) - return false; + if (m_parser_vars->m_materializer) { + uint32_t offset = 0; - if (log) - log->Printf("Placed at 0x%llx", (unsigned long long)offset); + Error err; - jit_vars->m_offset = offset; // TODO DoStructLayout() should not change this. + if (is_persistent_variable) { + ExpressionVariableSP var_sp(var->shared_from_this()); + offset = m_parser_vars->m_materializer->AddPersistentVariable( + var_sp, nullptr, err); + } else { + if (const lldb_private::Symbol *sym = parser_vars->m_lldb_sym) + offset = m_parser_vars->m_materializer->AddSymbol(*sym, err); + else if (const RegisterInfo *reg_info = var->GetRegisterInfo()) + offset = m_parser_vars->m_materializer->AddRegister(*reg_info, err); + else if (parser_vars->m_lldb_var) + offset = m_parser_vars->m_materializer->AddVariable( + parser_vars->m_lldb_var, err); } - return true; -} - -bool -ClangExpressionDeclMap::DoStructLayout () -{ - assert (m_struct_vars.get()); + if (!err.Success()) + return false; - if (m_struct_vars->m_struct_laid_out) - return true; + if (log) + log->Printf("Placed at 0x%llx", (unsigned long long)offset); - if (!m_parser_vars->m_materializer) - return false; + jit_vars->m_offset = + offset; // TODO DoStructLayout() should not change this. + } - m_struct_vars->m_struct_alignment = m_parser_vars->m_materializer->GetStructAlignment(); - m_struct_vars->m_struct_size = m_parser_vars->m_materializer->GetStructByteSize(); - m_struct_vars->m_struct_laid_out = true; - return true; + return true; } -bool ClangExpressionDeclMap::GetStructInfo -( - uint32_t &num_elements, - size_t &size, - lldb::offset_t &alignment -) -{ - assert (m_struct_vars.get()); +bool ClangExpressionDeclMap::DoStructLayout() { + assert(m_struct_vars.get()); - if (!m_struct_vars->m_struct_laid_out) - return false; + if (m_struct_vars->m_struct_laid_out) + return true; - num_elements = m_struct_members.GetSize(); - size = m_struct_vars->m_struct_size; - alignment = m_struct_vars->m_struct_alignment; + if (!m_parser_vars->m_materializer) + return false; - return true; + m_struct_vars->m_struct_alignment = + m_parser_vars->m_materializer->GetStructAlignment(); + m_struct_vars->m_struct_size = + m_parser_vars->m_materializer->GetStructByteSize(); + m_struct_vars->m_struct_laid_out = true; + return true; } -bool -ClangExpressionDeclMap::GetStructElement -( - const NamedDecl *&decl, - llvm::Value *&value, - lldb::offset_t &offset, - ConstString &name, - uint32_t index -) -{ - assert (m_struct_vars.get()); - - if (!m_struct_vars->m_struct_laid_out) - return false; +bool ClangExpressionDeclMap::GetStructInfo(uint32_t &num_elements, size_t &size, + lldb::offset_t &alignment) { + assert(m_struct_vars.get()); - if (index >= m_struct_members.GetSize()) - return false; + if (!m_struct_vars->m_struct_laid_out) + return false; - ExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index)); + num_elements = m_struct_members.GetSize(); + size = m_struct_vars->m_struct_size; + alignment = m_struct_vars->m_struct_alignment; - if (!member_sp) - return false; - - ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(member_sp.get())->GetParserVars(GetParserID()); - ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(member_sp.get())->GetJITVars(GetParserID()); + return true; +} - if (!parser_vars || - !jit_vars || - !member_sp->GetValueObject()) - return false; +bool ClangExpressionDeclMap::GetStructElement(const NamedDecl *&decl, + llvm::Value *&value, + lldb::offset_t &offset, + ConstString &name, + uint32_t index) { + assert(m_struct_vars.get()); - decl = parser_vars->m_named_decl; - value = parser_vars->m_llvm_value; - offset = jit_vars->m_offset; - name = member_sp->GetName(); + if (!m_struct_vars->m_struct_laid_out) + return false; - return true; -} + if (index >= m_struct_members.GetSize()) + return false; -bool -ClangExpressionDeclMap::GetFunctionInfo -( - const NamedDecl *decl, - uint64_t &ptr -) -{ - ClangExpressionVariable *entity(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID())); + ExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index)); - if (!entity) - return false; + if (!member_sp) + return false; - // We know m_parser_vars is valid since we searched for the variable by - // its NamedDecl + ClangExpressionVariable::ParserVars *parser_vars = + llvm::cast<ClangExpressionVariable>(member_sp.get()) + ->GetParserVars(GetParserID()); + ClangExpressionVariable::JITVars *jit_vars = + llvm::cast<ClangExpressionVariable>(member_sp.get()) + ->GetJITVars(GetParserID()); - ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + if (!parser_vars || !jit_vars || !member_sp->GetValueObject()) + return false; - ptr = parser_vars->m_lldb_value.GetScalar().ULongLong(); + decl = parser_vars->m_named_decl; + value = parser_vars->m_llvm_value; + offset = jit_vars->m_offset; + name = member_sp->GetName(); - return true; + return true; } -addr_t -ClangExpressionDeclMap::GetSymbolAddress (Target &target, - Process *process, - const ConstString &name, - lldb::SymbolType symbol_type, - lldb_private::Module *module) -{ - SymbolContextList sc_list; - - if (module) - module->FindSymbolsWithNameAndType(name, symbol_type, sc_list); - else - target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, sc_list); - - const uint32_t num_matches = sc_list.GetSize(); - addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; +bool ClangExpressionDeclMap::GetFunctionInfo(const NamedDecl *decl, + uint64_t &ptr) { + ClangExpressionVariable *entity(ClangExpressionVariable::FindVariableInList( + m_found_entities, decl, GetParserID())); - for (uint32_t i=0; i<num_matches && (symbol_load_addr == 0 || symbol_load_addr == LLDB_INVALID_ADDRESS); i++) - { - SymbolContext sym_ctx; - sc_list.GetContextAtIndex(i, sym_ctx); + if (!entity) + return false; - const Address sym_address = sym_ctx.symbol->GetAddress(); + // We know m_parser_vars is valid since we searched for the variable by + // its NamedDecl - if (!sym_address.IsValid()) - continue; + ClangExpressionVariable::ParserVars *parser_vars = + entity->GetParserVars(GetParserID()); - switch (sym_ctx.symbol->GetType()) - { - case eSymbolTypeCode: - case eSymbolTypeTrampoline: - symbol_load_addr = sym_address.GetCallableLoadAddress (&target); - break; - - case eSymbolTypeResolver: - symbol_load_addr = sym_address.GetCallableLoadAddress (&target, true); - break; + ptr = parser_vars->m_lldb_value.GetScalar().ULongLong(); - case eSymbolTypeReExported: - { - ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName(); - if (reexport_name) - { - ModuleSP reexport_module_sp; - ModuleSpec reexport_module_spec; - reexport_module_spec.GetPlatformFileSpec() = sym_ctx.symbol->GetReExportedSymbolSharedLibrary(); - if (reexport_module_spec.GetPlatformFileSpec()) - { - reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); - if (!reexport_module_sp) - { - reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); - reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); - } - } - symbol_load_addr = GetSymbolAddress(target, process, sym_ctx.symbol->GetReExportedSymbolName(), symbol_type, reexport_module_sp.get()); - } - } - break; + return true; +} - case eSymbolTypeData: - case eSymbolTypeRuntime: - case eSymbolTypeVariable: - case eSymbolTypeLocal: - case eSymbolTypeParam: - case eSymbolTypeInvalid: - case eSymbolTypeAbsolute: - case eSymbolTypeException: - case eSymbolTypeSourceFile: - case eSymbolTypeHeaderFile: - case eSymbolTypeObjectFile: - case eSymbolTypeCommonBlock: - case eSymbolTypeBlock: - case eSymbolTypeVariableType: - case eSymbolTypeLineEntry: - case eSymbolTypeLineHeader: - case eSymbolTypeScopeBegin: - case eSymbolTypeScopeEnd: - case eSymbolTypeAdditional: - case eSymbolTypeCompiler: - case eSymbolTypeInstrumentation: - case eSymbolTypeUndefined: - case eSymbolTypeObjCClass: - case eSymbolTypeObjCMetaClass: - case eSymbolTypeObjCIVar: - symbol_load_addr = sym_address.GetLoadAddress (&target); - break; +addr_t ClangExpressionDeclMap::GetSymbolAddress(Target &target, + Process *process, + const ConstString &name, + lldb::SymbolType symbol_type, + lldb_private::Module *module) { + SymbolContextList sc_list; + + if (module) + module->FindSymbolsWithNameAndType(name, symbol_type, sc_list); + else + target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, sc_list); + + const uint32_t num_matches = sc_list.GetSize(); + addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; + + for (uint32_t i = 0; + i < num_matches && + (symbol_load_addr == 0 || symbol_load_addr == LLDB_INVALID_ADDRESS); + i++) { + SymbolContext sym_ctx; + sc_list.GetContextAtIndex(i, sym_ctx); + + const Address sym_address = sym_ctx.symbol->GetAddress(); + + if (!sym_address.IsValid()) + continue; + + switch (sym_ctx.symbol->GetType()) { + case eSymbolTypeCode: + case eSymbolTypeTrampoline: + symbol_load_addr = sym_address.GetCallableLoadAddress(&target); + break; + + case eSymbolTypeResolver: + symbol_load_addr = sym_address.GetCallableLoadAddress(&target, true); + break; + + case eSymbolTypeReExported: { + ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName(); + if (reexport_name) { + ModuleSP reexport_module_sp; + ModuleSpec reexport_module_spec; + reexport_module_spec.GetPlatformFileSpec() = + sym_ctx.symbol->GetReExportedSymbolSharedLibrary(); + if (reexport_module_spec.GetPlatformFileSpec()) { + reexport_module_sp = + target.GetImages().FindFirstModule(reexport_module_spec); + if (!reexport_module_sp) { + reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); + reexport_module_sp = + target.GetImages().FindFirstModule(reexport_module_spec); + } } + symbol_load_addr = GetSymbolAddress( + target, process, sym_ctx.symbol->GetReExportedSymbolName(), + symbol_type, reexport_module_sp.get()); + } + } break; + + case eSymbolTypeData: + case eSymbolTypeRuntime: + case eSymbolTypeVariable: + case eSymbolTypeLocal: + case eSymbolTypeParam: + case eSymbolTypeInvalid: + case eSymbolTypeAbsolute: + case eSymbolTypeException: + case eSymbolTypeSourceFile: + case eSymbolTypeHeaderFile: + case eSymbolTypeObjectFile: + case eSymbolTypeCommonBlock: + case eSymbolTypeBlock: + case eSymbolTypeVariableType: + case eSymbolTypeLineEntry: + case eSymbolTypeLineHeader: + case eSymbolTypeScopeBegin: + case eSymbolTypeScopeEnd: + case eSymbolTypeAdditional: + case eSymbolTypeCompiler: + case eSymbolTypeInstrumentation: + case eSymbolTypeUndefined: + case eSymbolTypeObjCClass: + case eSymbolTypeObjCMetaClass: + case eSymbolTypeObjCIVar: + symbol_load_addr = sym_address.GetLoadAddress(&target); + break; } + } - if (symbol_load_addr == LLDB_INVALID_ADDRESS && process) - { - ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime(); + if (symbol_load_addr == LLDB_INVALID_ADDRESS && process) { + ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime(); - if (runtime) - { - symbol_load_addr = runtime->LookupRuntimeSymbol(name); - } + if (runtime) { + symbol_load_addr = runtime->LookupRuntimeSymbol(name); } + } - return symbol_load_addr; + return symbol_load_addr; } -addr_t -ClangExpressionDeclMap::GetSymbolAddress (const ConstString &name, lldb::SymbolType symbol_type) -{ - assert (m_parser_vars.get()); +addr_t ClangExpressionDeclMap::GetSymbolAddress(const ConstString &name, + lldb::SymbolType symbol_type) { + assert(m_parser_vars.get()); - if (!m_parser_vars->m_exe_ctx.GetTargetPtr()) - return false; + if (!m_parser_vars->m_exe_ctx.GetTargetPtr()) + return false; - return GetSymbolAddress(m_parser_vars->m_exe_ctx.GetTargetRef(), m_parser_vars->m_exe_ctx.GetProcessPtr(), name, symbol_type); + return GetSymbolAddress(m_parser_vars->m_exe_ctx.GetTargetRef(), + m_parser_vars->m_exe_ctx.GetProcessPtr(), name, + symbol_type); } -const Symbol * -ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target, - const ConstString &name, - lldb_private::Module *module) -{ - SymbolContextList sc_list; +const Symbol *ClangExpressionDeclMap::FindGlobalDataSymbol( + Target &target, const ConstString &name, lldb_private::Module *module) { + SymbolContextList sc_list; - if (module) - module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); - else - target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); - - const uint32_t matches = sc_list.GetSize(); - for (uint32_t i=0; i<matches; ++i) - { - SymbolContext sym_ctx; - sc_list.GetContextAtIndex(i, sym_ctx); - if (sym_ctx.symbol) - { - const Symbol *symbol = sym_ctx.symbol; - const Address sym_address = symbol->GetAddress(); - - if (sym_address.IsValid()) - { - switch (symbol->GetType()) - { - case eSymbolTypeData: - case eSymbolTypeRuntime: - case eSymbolTypeAbsolute: - case eSymbolTypeObjCClass: - case eSymbolTypeObjCMetaClass: - case eSymbolTypeObjCIVar: - if (symbol->GetDemangledNameIsSynthesized()) - { - // If the demangled name was synthesized, then don't use it - // for expressions. Only let the symbol match if the mangled - // named matches for these symbols. - if (symbol->GetMangled().GetMangledName() != name) - break; - } - return symbol; - - case eSymbolTypeReExported: - { - ConstString reexport_name = symbol->GetReExportedSymbolName(); - if (reexport_name) - { - ModuleSP reexport_module_sp; - ModuleSpec reexport_module_spec; - reexport_module_spec.GetPlatformFileSpec() = symbol->GetReExportedSymbolSharedLibrary(); - if (reexport_module_spec.GetPlatformFileSpec()) - { - reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); - if (!reexport_module_sp) - { - reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); - reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); - } - } - // Don't allow us to try and resolve a re-exported symbol if it is the same - // as the current symbol - if (name == symbol->GetReExportedSymbolName() && module == reexport_module_sp.get()) - return NULL; - - return FindGlobalDataSymbol(target, symbol->GetReExportedSymbolName(), reexport_module_sp.get()); - } - } - break; - - case eSymbolTypeCode: // We already lookup functions elsewhere - case eSymbolTypeVariable: - case eSymbolTypeLocal: - case eSymbolTypeParam: - case eSymbolTypeTrampoline: - case eSymbolTypeInvalid: - case eSymbolTypeException: - case eSymbolTypeSourceFile: - case eSymbolTypeHeaderFile: - case eSymbolTypeObjectFile: - case eSymbolTypeCommonBlock: - case eSymbolTypeBlock: - case eSymbolTypeVariableType: - case eSymbolTypeLineEntry: - case eSymbolTypeLineHeader: - case eSymbolTypeScopeBegin: - case eSymbolTypeScopeEnd: - case eSymbolTypeAdditional: - case eSymbolTypeCompiler: - case eSymbolTypeInstrumentation: - case eSymbolTypeUndefined: - case eSymbolTypeResolver: - break; - } + if (module) + module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); + else + target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, + sc_list); + + const uint32_t matches = sc_list.GetSize(); + for (uint32_t i = 0; i < matches; ++i) { + SymbolContext sym_ctx; + sc_list.GetContextAtIndex(i, sym_ctx); + if (sym_ctx.symbol) { + const Symbol *symbol = sym_ctx.symbol; + const Address sym_address = symbol->GetAddress(); + + if (sym_address.IsValid()) { + switch (symbol->GetType()) { + case eSymbolTypeData: + case eSymbolTypeRuntime: + case eSymbolTypeAbsolute: + case eSymbolTypeObjCClass: + case eSymbolTypeObjCMetaClass: + case eSymbolTypeObjCIVar: + if (symbol->GetDemangledNameIsSynthesized()) { + // If the demangled name was synthesized, then don't use it + // for expressions. Only let the symbol match if the mangled + // named matches for these symbols. + if (symbol->GetMangled().GetMangledName() != name) + break; + } + return symbol; + + case eSymbolTypeReExported: { + ConstString reexport_name = symbol->GetReExportedSymbolName(); + if (reexport_name) { + ModuleSP reexport_module_sp; + ModuleSpec reexport_module_spec; + reexport_module_spec.GetPlatformFileSpec() = + symbol->GetReExportedSymbolSharedLibrary(); + if (reexport_module_spec.GetPlatformFileSpec()) { + reexport_module_sp = + target.GetImages().FindFirstModule(reexport_module_spec); + if (!reexport_module_sp) { + reexport_module_spec.GetPlatformFileSpec() + .GetDirectory() + .Clear(); + reexport_module_sp = + target.GetImages().FindFirstModule(reexport_module_spec); + } } + // Don't allow us to try and resolve a re-exported symbol if it is + // the same + // as the current symbol + if (name == symbol->GetReExportedSymbolName() && + module == reexport_module_sp.get()) + return NULL; + + return FindGlobalDataSymbol(target, + symbol->GetReExportedSymbolName(), + reexport_module_sp.get()); + } + } break; + + case eSymbolTypeCode: // We already lookup functions elsewhere + case eSymbolTypeVariable: + case eSymbolTypeLocal: + case eSymbolTypeParam: + case eSymbolTypeTrampoline: + case eSymbolTypeInvalid: + case eSymbolTypeException: + case eSymbolTypeSourceFile: + case eSymbolTypeHeaderFile: + case eSymbolTypeObjectFile: + case eSymbolTypeCommonBlock: + case eSymbolTypeBlock: + case eSymbolTypeVariableType: + case eSymbolTypeLineEntry: + case eSymbolTypeLineHeader: + case eSymbolTypeScopeBegin: + case eSymbolTypeScopeEnd: + case eSymbolTypeAdditional: + case eSymbolTypeCompiler: + case eSymbolTypeInstrumentation: + case eSymbolTypeUndefined: + case eSymbolTypeResolver: + break; } + } } + } - return NULL; + return NULL; } -lldb::VariableSP -ClangExpressionDeclMap::FindGlobalVariable -( - Target &target, - ModuleSP &module, - const ConstString &name, - CompilerDeclContext *namespace_decl, - TypeFromUser *type -) -{ - VariableList vars; - - if (module && namespace_decl) - module->FindGlobalVariables (name, namespace_decl, true, -1, vars); - else - target.GetImages().FindGlobalVariables(name, true, -1, vars); - - if (vars.GetSize()) - { - if (type) - { - for (size_t i = 0; i < vars.GetSize(); ++i) - { - VariableSP var_sp = vars.GetVariableAtIndex(i); - - if (ClangASTContext::AreTypesSame(*type, var_sp->GetType()->GetFullCompilerType ())) - return var_sp; - } - } - else - { - return vars.GetVariableAtIndex(0); - } +lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable( + Target &target, ModuleSP &module, const ConstString &name, + CompilerDeclContext *namespace_decl, TypeFromUser *type) { + VariableList vars; + + if (module && namespace_decl) + module->FindGlobalVariables(name, namespace_decl, true, -1, vars); + else + target.GetImages().FindGlobalVariables(name, true, -1, vars); + + if (vars.GetSize()) { + if (type) { + for (size_t i = 0; i < vars.GetSize(); ++i) { + VariableSP var_sp = vars.GetVariableAtIndex(i); + + if (ClangASTContext::AreTypesSame( + *type, var_sp->GetType()->GetFullCompilerType())) + return var_sp; + } + } else { + return vars.GetVariableAtIndex(0); } + } - return VariableSP(); + return VariableSP(); } -ClangASTContext * -ClangExpressionDeclMap::GetClangASTContext () -{ - StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); - if (frame == nullptr) - return nullptr; +ClangASTContext *ClangExpressionDeclMap::GetClangASTContext() { + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + if (frame == nullptr) + return nullptr; - SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); - if (sym_ctx.block == nullptr) - return nullptr; + SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | + lldb::eSymbolContextBlock); + if (sym_ctx.block == nullptr) + return nullptr; - CompilerDeclContext frame_decl_context = sym_ctx.block->GetDeclContext(); - if (!frame_decl_context) - return nullptr; + CompilerDeclContext frame_decl_context = sym_ctx.block->GetDeclContext(); + if (!frame_decl_context) + return nullptr; - return llvm::dyn_cast_or_null<ClangASTContext>(frame_decl_context.GetTypeSystem()); + return llvm::dyn_cast_or_null<ClangASTContext>( + frame_decl_context.GetTypeSystem()); } // Interface for ClangASTSource -void -ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context) -{ - assert (m_ast_context); +void ClangExpressionDeclMap::FindExternalVisibleDecls( + NameSearchContext &context) { + assert(m_ast_context); - ClangASTMetrics::RegisterVisibleQuery(); + ClangASTMetrics::RegisterVisibleQuery(); - const ConstString name(context.m_decl_name.getAsString().c_str()); + const ConstString name(context.m_decl_name.getAsString().c_str()); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (GetImportInProgress()) - { - if (log && log->GetVerbose()) - log->Printf("Ignoring a query during an import"); - return; + if (GetImportInProgress()) { + if (log && log->GetVerbose()) + log->Printf("Ignoring a query during an import"); + return; + } + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + if (log) { + if (!context.m_decl_context) + log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " + "'%s' in a NULL DeclContext", + current_id, name.GetCString()); + else if (const NamedDecl *context_named_decl = + dyn_cast<NamedDecl>(context.m_decl_context)) + log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " + "'%s' in '%s'", + current_id, name.GetCString(), + context_named_decl->getNameAsString().c_str()); + else + log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " + "'%s' in a '%s'", + current_id, name.GetCString(), + context.m_decl_context->getDeclKindName()); + } + + if (const NamespaceDecl *namespace_context = + dyn_cast<NamespaceDecl>(context.m_decl_context)) { + if (namespace_context->getName().str() == + std::string(g_lldb_local_vars_namespace_cstr)) { + CompilerDeclContext compiler_decl_ctx( + GetClangASTContext(), const_cast<void *>(static_cast<const void *>( + context.m_decl_context))); + FindExternalVisibleDecls(context, lldb::ModuleSP(), compiler_decl_ctx, + current_id); + return; } - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; + ClangASTImporter::NamespaceMapSP namespace_map = + m_ast_importer_sp->GetNamespaceMap(namespace_context); - if (log) - { - if (!context.m_decl_context) - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a NULL DeclContext", current_id, name.GetCString()); - else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context)) - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in '%s'", current_id, name.GetCString(), context_named_decl->getNameAsString().c_str()); - else - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a '%s'", current_id, name.GetCString(), context.m_decl_context->getDeclKindName()); + if (log && log->GetVerbose()) + log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)", + current_id, static_cast<void *>(namespace_map.get()), + (int)namespace_map->size()); + + if (!namespace_map) + return; + + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), + e = namespace_map->end(); + i != e; ++i) { + if (log) + log->Printf(" CEDM::FEVD[%u] Searching namespace %s in module %s", + current_id, i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); + + FindExternalVisibleDecls(context, i->first, i->second, current_id); } + } else if (isa<TranslationUnitDecl>(context.m_decl_context)) { + CompilerDeclContext namespace_decl; - if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context)) - { - if (namespace_context->getName().str() == std::string(g_lldb_local_vars_namespace_cstr)) - { - CompilerDeclContext compiler_decl_ctx(GetClangASTContext(), const_cast<void *>(static_cast<const void *>(context.m_decl_context))); - FindExternalVisibleDecls(context, lldb::ModuleSP(), compiler_decl_ctx, current_id); - return; - } + if (log) + log->Printf(" CEDM::FEVD[%u] Searching the root namespace", current_id); - ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); + FindExternalVisibleDecls(context, lldb::ModuleSP(), namespace_decl, + current_id); + } - if (log && log->GetVerbose()) - log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)", - current_id, static_cast<void*>(namespace_map.get()), - (int)namespace_map->size()); + if (!context.m_found.variable && !context.m_found.local_vars_nsp) + ClangASTSource::FindExternalVisibleDecls(context); +} - if (!namespace_map) - return; +void ClangExpressionDeclMap::FindExternalVisibleDecls( + NameSearchContext &context, lldb::ModuleSP module_sp, + CompilerDeclContext &namespace_decl, unsigned int current_id) { + assert(m_ast_context); - for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); - i != e; - ++i) - { - if (log) - log->Printf(" CEDM::FEVD[%u] Searching namespace %s in module %s", - current_id, - i->second.GetName().AsCString(), - i->first->GetFileSpec().GetFilename().GetCString()); - - FindExternalVisibleDecls(context, - i->first, - i->second, - current_id); + std::function<void(clang::FunctionDecl *)> MaybeRegisterFunctionBody = + [this](clang::FunctionDecl *copied_function_decl) { + if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) { + DeclGroupRef decl_group_ref(copied_function_decl); + m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref); } - } - else if (isa<TranslationUnitDecl>(context.m_decl_context)) - { - CompilerDeclContext namespace_decl; + }; - if (log) - log->Printf(" CEDM::FEVD[%u] Searching the root namespace", current_id); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - FindExternalVisibleDecls(context, - lldb::ModuleSP(), - namespace_decl, - current_id); - } + SymbolContextList sc_list; - if (!context.m_found.variable && !context.m_found.local_vars_nsp) - ClangASTSource::FindExternalVisibleDecls(context); -} + const ConstString name(context.m_decl_name.getAsString().c_str()); -void -ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, - lldb::ModuleSP module_sp, - CompilerDeclContext &namespace_decl, - unsigned int current_id) -{ - assert (m_ast_context); - - std::function<void (clang::FunctionDecl *)> MaybeRegisterFunctionBody = - [this](clang::FunctionDecl *copied_function_decl) - { - if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) - { - DeclGroupRef decl_group_ref(copied_function_decl); - m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref); - } - }; + const char *name_unique_cstr = name.GetCString(); + + if (name_unique_cstr == NULL) + return; + static ConstString id_name("id"); + static ConstString Class_name("Class"); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (name == id_name || name == Class_name) + return; - SymbolContextList sc_list; + // Only look for functions by name out in our symbols if the function + // doesn't start with our phony prefix of '$' + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + SymbolContext sym_ctx; + if (frame != nullptr) + sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | + lldb::eSymbolContextBlock); - const ConstString name(context.m_decl_name.getAsString().c_str()); + // Try the persistent decls, which take precedence over all else. + if (!namespace_decl) { + do { + if (!target) + break; - const char *name_unique_cstr = name.GetCString(); + ClangASTContext *scratch_clang_ast_context = + target->GetScratchClangASTContext(); - if (name_unique_cstr == NULL) - return; + if (!scratch_clang_ast_context) + break; - static ConstString id_name("id"); - static ConstString Class_name("Class"); + ASTContext *scratch_ast_context = + scratch_clang_ast_context->getASTContext(); - if (name == id_name || name == Class_name) - return; + if (!scratch_ast_context) + break; - // Only look for functions by name out in our symbols if the function - // doesn't start with our phony prefix of '$' - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); - SymbolContext sym_ctx; - if (frame != nullptr) - sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); - - // Try the persistent decls, which take precedence over all else. - if (!namespace_decl) - { - do - { - if (!target) - break; - - ClangASTContext *scratch_clang_ast_context = target->GetScratchClangASTContext(); - - if (!scratch_clang_ast_context) - break; - - ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext(); - - if (!scratch_ast_context) - break; - - NamedDecl *persistent_decl = m_parser_vars->m_persistent_vars->GetPersistentDecl(name); - - if (!persistent_decl) - break; - - Decl *parser_persistent_decl = m_ast_importer_sp->CopyDecl(m_ast_context, scratch_ast_context, persistent_decl); - - if (!parser_persistent_decl) - break; - - NamedDecl *parser_named_decl = dyn_cast<NamedDecl>(parser_persistent_decl); - - if (!parser_named_decl) - break; - - if (clang::FunctionDecl *parser_function_decl = llvm::dyn_cast<clang::FunctionDecl>(parser_named_decl)) - { - MaybeRegisterFunctionBody(parser_function_decl); - } - - if (log) - log->Printf(" CEDM::FEVD[%u] Found persistent decl %s", current_id, name.GetCString()); - - context.AddNamedDecl(parser_named_decl); - } while (0); - } - - if (name_unique_cstr[0] == '$' && !namespace_decl) - { - static ConstString g_lldb_class_name ("$__lldb_class"); + NamedDecl *persistent_decl = + m_parser_vars->m_persistent_vars->GetPersistentDecl(name); - if (name == g_lldb_class_name) - { - // Clang is looking for the type of "this" + if (!persistent_decl) + break; - if (frame == NULL) - return; + Decl *parser_persistent_decl = m_ast_importer_sp->CopyDecl( + m_ast_context, scratch_ast_context, persistent_decl); + if (!parser_persistent_decl) + break; - // Find the block that defines the function represented by "sym_ctx" - Block *function_block = sym_ctx.GetFunctionBlock(); + NamedDecl *parser_named_decl = + dyn_cast<NamedDecl>(parser_persistent_decl); - if (!function_block) - return; + if (!parser_named_decl) + break; - CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); + if (clang::FunctionDecl *parser_function_decl = + llvm::dyn_cast<clang::FunctionDecl>(parser_named_decl)) { + MaybeRegisterFunctionBody(parser_function_decl); + } - if (!function_decl_ctx) - return; + if (log) + log->Printf(" CEDM::FEVD[%u] Found persistent decl %s", current_id, + name.GetCString()); - clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx); + context.AddNamedDecl(parser_named_decl); + } while (0); + } - if (method_decl) - { - clang::CXXRecordDecl *class_decl = method_decl->getParent(); + if (name_unique_cstr[0] == '$' && !namespace_decl) { + static ConstString g_lldb_class_name("$__lldb_class"); - QualType class_qual_type(class_decl->getTypeForDecl(), 0); + if (name == g_lldb_class_name) { + // Clang is looking for the type of "this" - TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(), - ClangASTContext::GetASTContext(&class_decl->getASTContext())); + if (frame == NULL) + return; - if (log) - { - ASTDumper ast_dumper(class_qual_type); - log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString()); - } + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); - AddThisType(context, class_user_type, current_id); + if (!function_block) + return; - if (method_decl->isInstance()) - { - // self is a pointer to the object + CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); - QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type); + if (!function_decl_ctx) + return; - TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), - ClangASTContext::GetASTContext(&method_decl->getASTContext())); + clang::CXXMethodDecl *method_decl = + ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx); - m_struct_vars->m_object_pointer_type = self_user_type; - } - } - else - { - // This branch will get hit if we are executing code in the context of a function that - // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a - // method of the class. In that case, just look up the "this" variable in the current - // scope and use its type. - // FIXME: This code is formally correct, but clang doesn't currently emit DW_AT_object_pointer - // for C++ so it hasn't actually been tested. - - VariableList *vars = frame->GetVariableList(false); - - lldb::VariableSP this_var = vars->FindVariable(ConstString("this")); - - if (this_var && - this_var->IsInScope(frame) && - this_var->LocationIsValidForFrame (frame)) - { - Type *this_type = this_var->GetType(); - - if (!this_type) - return; - - TypeFromUser pointee_type = this_type->GetForwardCompilerType ().GetPointeeType(); - - if (pointee_type.IsValid()) - { - if (log) - { - ASTDumper ast_dumper(pointee_type); - log->Printf(" FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString()); - } - - AddThisType(context, pointee_type, current_id); - TypeFromUser this_user_type(this_type->GetFullCompilerType ()); - m_struct_vars->m_object_pointer_type = this_user_type; - return; - } - } + if (method_decl) { + clang::CXXRecordDecl *class_decl = method_decl->getParent(); + + QualType class_qual_type(class_decl->getTypeForDecl(), 0); + + TypeFromUser class_user_type( + class_qual_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&class_decl->getASTContext())); + + if (log) { + ASTDumper ast_dumper(class_qual_type); + log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", + current_id, ast_dumper.GetCString()); + } + + AddThisType(context, class_user_type, current_id); + + if (method_decl->isInstance()) { + // self is a pointer to the object + + QualType class_pointer_type = + method_decl->getASTContext().getPointerType(class_qual_type); + + TypeFromUser self_user_type( + class_pointer_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); + + m_struct_vars->m_object_pointer_type = self_user_type; + } + } else { + // This branch will get hit if we are executing code in the context of a + // function that + // claims to have an object pointer (through DW_AT_object_pointer?) but + // is not formally a + // method of the class. In that case, just look up the "this" variable + // in the current + // scope and use its type. + // FIXME: This code is formally correct, but clang doesn't currently + // emit DW_AT_object_pointer + // for C++ so it hasn't actually been tested. + + VariableList *vars = frame->GetVariableList(false); + + lldb::VariableSP this_var = vars->FindVariable(ConstString("this")); + + if (this_var && this_var->IsInScope(frame) && + this_var->LocationIsValidForFrame(frame)) { + Type *this_type = this_var->GetType(); + + if (!this_type) + return; + + TypeFromUser pointee_type = + this_type->GetForwardCompilerType().GetPointeeType(); + + if (pointee_type.IsValid()) { + if (log) { + ASTDumper ast_dumper(pointee_type); + log->Printf(" FEVD[%u] Adding type for $__lldb_class: %s", + current_id, ast_dumper.GetCString()); } + AddThisType(context, pointee_type, current_id); + TypeFromUser this_user_type(this_type->GetFullCompilerType()); + m_struct_vars->m_object_pointer_type = this_user_type; return; + } } + } - static ConstString g_lldb_objc_class_name ("$__lldb_objc_class"); - if (name == g_lldb_objc_class_name) - { - // Clang is looking for the type of "*self" + return; + } - if (!frame) - return; + static ConstString g_lldb_objc_class_name("$__lldb_objc_class"); + if (name == g_lldb_objc_class_name) { + // Clang is looking for the type of "*self" - SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); + if (!frame) + return; - // Find the block that defines the function represented by "sym_ctx" - Block *function_block = sym_ctx.GetFunctionBlock(); + SymbolContext sym_ctx = frame->GetSymbolContext( + lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); - if (!function_block) - return; + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); - CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); + if (!function_block) + return; - if (!function_decl_ctx) - return; + CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); - clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); + if (!function_decl_ctx) + return; - if (method_decl) - { - ObjCInterfaceDecl* self_interface = method_decl->getClassInterface(); + clang::ObjCMethodDecl *method_decl = + ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); - if (!self_interface) - return; + if (method_decl) { + ObjCInterfaceDecl *self_interface = method_decl->getClassInterface(); - const clang::Type *interface_type = self_interface->getTypeForDecl(); + if (!self_interface) + return; - if (!interface_type) - return; // This is unlikely, but we have seen crashes where this occurred + const clang::Type *interface_type = self_interface->getTypeForDecl(); - TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(), - ClangASTContext::GetASTContext(&method_decl->getASTContext())); + if (!interface_type) + return; // This is unlikely, but we have seen crashes where this + // occurred - if (log) - { - ASTDumper ast_dumper(interface_type); - log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString()); - } + TypeFromUser class_user_type( + QualType(interface_type, 0).getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); - AddOneType(context, class_user_type, current_id); + if (log) { + ASTDumper ast_dumper(interface_type); + log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", + current_id, ast_dumper.GetCString()); + } - if (method_decl->isInstanceMethod()) - { - // self is a pointer to the object + AddOneType(context, class_user_type, current_id); - QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0)); + if (method_decl->isInstanceMethod()) { + // self is a pointer to the object - TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), - ClangASTContext::GetASTContext(&method_decl->getASTContext())); + QualType class_pointer_type = + method_decl->getASTContext().getObjCObjectPointerType( + QualType(interface_type, 0)); - m_struct_vars->m_object_pointer_type = self_user_type; - } - else - { - // self is a Class pointer - QualType class_type = method_decl->getASTContext().getObjCClassType(); + TypeFromUser self_user_type( + class_pointer_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); - TypeFromUser self_user_type(class_type.getAsOpaquePtr(), - ClangASTContext::GetASTContext(&method_decl->getASTContext())); + m_struct_vars->m_object_pointer_type = self_user_type; + } else { + // self is a Class pointer + QualType class_type = method_decl->getASTContext().getObjCClassType(); - m_struct_vars->m_object_pointer_type = self_user_type; - } + TypeFromUser self_user_type( + class_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); - return; - } - else - { - // This branch will get hit if we are executing code in the context of a function that - // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a - // method of the class. In that case, just look up the "self" variable in the current - // scope and use its type. + m_struct_vars->m_object_pointer_type = self_user_type; + } - VariableList *vars = frame->GetVariableList(false); + return; + } else { + // This branch will get hit if we are executing code in the context of a + // function that + // claims to have an object pointer (through DW_AT_object_pointer?) but + // is not formally a + // method of the class. In that case, just look up the "self" variable + // in the current + // scope and use its type. - lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); + VariableList *vars = frame->GetVariableList(false); - if (self_var && - self_var->IsInScope(frame) && - self_var->LocationIsValidForFrame (frame)) - { - Type *self_type = self_var->GetType(); + lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); - if (!self_type) - return; + if (self_var && self_var->IsInScope(frame) && + self_var->LocationIsValidForFrame(frame)) { + Type *self_type = self_var->GetType(); - CompilerType self_clang_type = self_type->GetFullCompilerType (); + if (!self_type) + return; - if (ClangASTContext::IsObjCClassType(self_clang_type)) - { - return; - } - else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type)) - { - self_clang_type = self_clang_type.GetPointeeType(); + CompilerType self_clang_type = self_type->GetFullCompilerType(); - if (!self_clang_type) - return; + if (ClangASTContext::IsObjCClassType(self_clang_type)) { + return; + } else if (ClangASTContext::IsObjCObjectPointerType( + self_clang_type)) { + self_clang_type = self_clang_type.GetPointeeType(); - if (log) - { - ASTDumper ast_dumper(self_type->GetFullCompilerType ()); - log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString()); - } + if (!self_clang_type) + return; - TypeFromUser class_user_type (self_clang_type); + if (log) { + ASTDumper ast_dumper(self_type->GetFullCompilerType()); + log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", + current_id, ast_dumper.GetCString()); + } - AddOneType(context, class_user_type, current_id); + TypeFromUser class_user_type(self_clang_type); - TypeFromUser self_user_type(self_type->GetFullCompilerType ()); + AddOneType(context, class_user_type, current_id); - m_struct_vars->m_object_pointer_type = self_user_type; - return; - } - } - } + TypeFromUser self_user_type(self_type->GetFullCompilerType()); + m_struct_vars->m_object_pointer_type = self_user_type; return; + } } + } - if (name == ConstString(g_lldb_local_vars_namespace_cstr)) - { - CompilerDeclContext frame_decl_context = sym_ctx.block != nullptr ? - sym_ctx.block->GetDeclContext() : - CompilerDeclContext(); - - if (frame_decl_context) - { - ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(frame_decl_context.GetTypeSystem()); - - if (ast) - { - clang::NamespaceDecl *namespace_decl = ClangASTContext::GetUniqueNamespaceDeclaration( - m_ast_context, name_unique_cstr, nullptr); - if (namespace_decl) - { - context.AddNamedDecl(namespace_decl); - clang::DeclContext *clang_decl_ctx = clang::Decl::castToDeclContext(namespace_decl); - clang_decl_ctx->setHasExternalVisibleStorage(true); - context.m_found.local_vars_nsp = true; - } - } - } + return; + } - return; + if (name == ConstString(g_lldb_local_vars_namespace_cstr)) { + CompilerDeclContext frame_decl_context = + sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() + : CompilerDeclContext(); + + if (frame_decl_context) { + ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>( + frame_decl_context.GetTypeSystem()); + + if (ast) { + clang::NamespaceDecl *namespace_decl = + ClangASTContext::GetUniqueNamespaceDeclaration( + m_ast_context, name_unique_cstr, nullptr); + if (namespace_decl) { + context.AddNamedDecl(namespace_decl); + clang::DeclContext *clang_decl_ctx = + clang::Decl::castToDeclContext(namespace_decl); + clang_decl_ctx->setHasExternalVisibleStorage(true); + context.m_found.local_vars_nsp = true; + } } + } - // any other $__lldb names should be weeded out now - if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1)) - return; + return; + } - ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name)); + // any other $__lldb names should be weeded out now + if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1)) + return; - if (pvar_sp) - { - AddOneVariable(context, pvar_sp, current_id); - return; - } + ExpressionVariableSP pvar_sp( + m_parser_vars->m_persistent_vars->GetVariable(name)); - const char *reg_name(&name.GetCString()[1]); + if (pvar_sp) { + AddOneVariable(context, pvar_sp, current_id); + return; + } - if (m_parser_vars->m_exe_ctx.GetRegisterContext()) - { - const RegisterInfo *reg_info(m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(reg_name)); + const char *reg_name(&name.GetCString()[1]); - if (reg_info) - { - if (log) - log->Printf(" CEDM::FEVD[%u] Found register %s", current_id, reg_info->name); + if (m_parser_vars->m_exe_ctx.GetRegisterContext()) { + const RegisterInfo *reg_info( + m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName( + reg_name)); - AddOneRegister(context, reg_info, current_id); - } - } + if (reg_info) { + if (log) + log->Printf(" CEDM::FEVD[%u] Found register %s", current_id, + reg_info->name); + + AddOneRegister(context, reg_info, current_id); + } } - else - { - ValueObjectSP valobj; - VariableSP var; - - bool local_var_lookup = !namespace_decl || - (namespace_decl.GetName() == ConstString(g_lldb_local_vars_namespace_cstr)); - if (frame && local_var_lookup) - { - CompilerDeclContext compiler_decl_context = sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() : CompilerDeclContext(); - - if (compiler_decl_context) - { - // Make sure that the variables are parsed so that we have the declarations. - VariableListSP vars = frame->GetInScopeVariableList(true); - for (size_t i = 0; i < vars->GetSize(); i++) - vars->GetVariableAtIndex(i)->GetDecl(); - - // Search for declarations matching the name. Do not include imported decls - // in the search if we are looking for decls in the artificial namespace - // $__lldb_local_vars. - std::vector<CompilerDecl> found_decls = compiler_decl_context.FindDeclByName(name, namespace_decl.IsValid()); - - bool variable_found = false; - for (CompilerDecl decl : found_decls) - { - for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) - { - VariableSP candidate_var = vars->GetVariableAtIndex(vi); - if (candidate_var->GetDecl() == decl) - { - var = candidate_var; - break; - } - } - - if (var) - { - variable_found = true; - valobj = ValueObjectVariable::Create(frame, var); - AddOneVariable(context, var, valobj, current_id); - context.m_found.variable = true; - } - } - if (variable_found) - return; + } else { + ValueObjectSP valobj; + VariableSP var; + + bool local_var_lookup = + !namespace_decl || (namespace_decl.GetName() == + ConstString(g_lldb_local_vars_namespace_cstr)); + if (frame && local_var_lookup) { + CompilerDeclContext compiler_decl_context = + sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() + : CompilerDeclContext(); + + if (compiler_decl_context) { + // Make sure that the variables are parsed so that we have the + // declarations. + VariableListSP vars = frame->GetInScopeVariableList(true); + for (size_t i = 0; i < vars->GetSize(); i++) + vars->GetVariableAtIndex(i)->GetDecl(); + + // Search for declarations matching the name. Do not include imported + // decls + // in the search if we are looking for decls in the artificial namespace + // $__lldb_local_vars. + std::vector<CompilerDecl> found_decls = + compiler_decl_context.FindDeclByName(name, + namespace_decl.IsValid()); + + bool variable_found = false; + for (CompilerDecl decl : found_decls) { + for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) { + VariableSP candidate_var = vars->GetVariableAtIndex(vi); + if (candidate_var->GetDecl() == decl) { + var = candidate_var; + break; } + } + + if (var) { + variable_found = true; + valobj = ValueObjectVariable::Create(frame, var); + AddOneVariable(context, var, valobj, current_id); + context.m_found.variable = true; + } } - if (target) - { - var = FindGlobalVariable (*target, - module_sp, - name, - &namespace_decl, - NULL); - - if (var) - { - valobj = ValueObjectVariable::Create(target, var); - AddOneVariable(context, var, valobj, current_id); - context.m_found.variable = true; - return; + if (variable_found) + return; + } + } + if (target) { + var = FindGlobalVariable(*target, module_sp, name, &namespace_decl, NULL); + + if (var) { + valobj = ValueObjectVariable::Create(target, var); + AddOneVariable(context, var, valobj, current_id); + context.m_found.variable = true; + return; + } + } + + std::vector<clang::NamedDecl *> decls_from_modules; + + if (target) { + if (ClangModulesDeclVendor *decl_vendor = + target->GetClangModulesDeclVendor()) { + decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules); + } + } + + if (!context.m_found.variable) { + const bool include_inlines = false; + const bool append = false; + + if (namespace_decl && module_sp) { + const bool include_symbols = false; + + module_sp->FindFunctions(name, &namespace_decl, eFunctionNameTypeBase, + include_symbols, include_inlines, append, + sc_list); + } else if (target && !namespace_decl) { + const bool include_symbols = true; + + // TODO Fix FindFunctions so that it doesn't return + // instance methods for eFunctionNameTypeBase. + + target->GetImages().FindFunctions(name, eFunctionNameTypeFull, + include_symbols, include_inlines, + append, sc_list); + } + + // If we found more than one function, see if we can use the + // frame's decl context to remove functions that are shadowed + // by other functions which match in type but are nearer in scope. + // + // AddOneFunction will not add a function whose type has already been + // added, so if there's another function in the list with a matching + // type, check to see if their decl context is a parent of the current + // frame's or was imported via a and using statement, and pick the + // best match according to lookup rules. + if (sc_list.GetSize() > 1) { + // Collect some info about our frame's context. + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + SymbolContext frame_sym_ctx; + if (frame != nullptr) + frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | + lldb::eSymbolContextBlock); + CompilerDeclContext frame_decl_context = + frame_sym_ctx.block != nullptr + ? frame_sym_ctx.block->GetDeclContext() + : CompilerDeclContext(); + + // We can't do this without a compiler decl context for our frame. + if (frame_decl_context) { + clang::DeclContext *frame_decl_ctx = + (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext(); + ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>( + frame_decl_context.GetTypeSystem()); + + // Structure to hold the info needed when comparing function + // declarations. + struct FuncDeclInfo { + ConstString m_name; + CompilerType m_copied_type; + uint32_t m_decl_lvl; + SymbolContext m_sym_ctx; + }; + + // First, symplify things by looping through the symbol contexts + // to remove unwanted functions and separate out the functions we + // want to compare and prune into a separate list. + // Cache the info needed about the function declarations in a + // vector for efficiency. + SymbolContextList sc_sym_list; + uint32_t num_indices = sc_list.GetSize(); + std::vector<FuncDeclInfo> fdi_cache; + fdi_cache.reserve(num_indices); + for (uint32_t index = 0; index < num_indices; ++index) { + FuncDeclInfo fdi; + SymbolContext sym_ctx; + sc_list.GetContextAtIndex(index, sym_ctx); + + // We don't know enough about symbols to compare them, + // but we should keep them in the list. + Function *function = sym_ctx.function; + if (!function) { + sc_sym_list.Append(sym_ctx); + continue; } - } - - std::vector<clang::NamedDecl *> decls_from_modules; - - if (target) - { - if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) - { - decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules); + // Filter out functions without declaration contexts, as well as + // class/instance methods, since they'll be skipped in the + // code that follows anyway. + CompilerDeclContext func_decl_context = function->GetDeclContext(); + if (!func_decl_context || + func_decl_context.IsClassMethod(nullptr, nullptr, nullptr)) + continue; + // We can only prune functions for which we can copy the type. + CompilerType func_clang_type = + function->GetType()->GetFullCompilerType(); + CompilerType copied_func_type = GuardedCopyType(func_clang_type); + if (!copied_func_type) { + sc_sym_list.Append(sym_ctx); + continue; } - } - if (!context.m_found.variable) - { - const bool include_inlines = false; - const bool append = false; - - if (namespace_decl && module_sp) - { - const bool include_symbols = false; - - module_sp->FindFunctions(name, - &namespace_decl, - eFunctionNameTypeBase, - include_symbols, - include_inlines, - append, - sc_list); + fdi.m_sym_ctx = sym_ctx; + fdi.m_name = function->GetName(); + fdi.m_copied_type = copied_func_type; + fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL; + if (fdi.m_copied_type && func_decl_context) { + // Call CountDeclLevels to get the number of parent scopes we + // have to look through before we find the function declaration. + // When comparing functions of the same type, the one with a + // lower count will be closer to us in the lookup scope and + // shadows the other. + clang::DeclContext *func_decl_ctx = + (clang::DeclContext *) + func_decl_context.GetOpaqueDeclContext(); + fdi.m_decl_lvl = + ast->CountDeclLevels(frame_decl_ctx, func_decl_ctx, + &fdi.m_name, &fdi.m_copied_type); } - else if (target && !namespace_decl) - { - const bool include_symbols = true; - - // TODO Fix FindFunctions so that it doesn't return - // instance methods for eFunctionNameTypeBase. - - target->GetImages().FindFunctions(name, - eFunctionNameTypeFull, - include_symbols, - include_inlines, - append, - sc_list); + fdi_cache.emplace_back(fdi); + } + + // Loop through the functions in our cache looking for matching types, + // then compare their scope levels to see which is closer. + std::multimap<CompilerType, const FuncDeclInfo *> matches; + for (const FuncDeclInfo &fdi : fdi_cache) { + const CompilerType t = fdi.m_copied_type; + auto q = matches.find(t); + if (q != matches.end()) { + if (q->second->m_decl_lvl > fdi.m_decl_lvl) + // This function is closer; remove the old set. + matches.erase(t); + else if (q->second->m_decl_lvl < fdi.m_decl_lvl) + // The functions in our set are closer - skip this one. + continue; } + matches.insert(std::make_pair(t, &fdi)); + } - // If we found more than one function, see if we can use the - // frame's decl context to remove functions that are shadowed - // by other functions which match in type but are nearer in scope. - // - // AddOneFunction will not add a function whose type has already been - // added, so if there's another function in the list with a matching - // type, check to see if their decl context is a parent of the current - // frame's or was imported via a and using statement, and pick the - // best match according to lookup rules. - if (sc_list.GetSize() > 1) - { - // Collect some info about our frame's context. - StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); - SymbolContext frame_sym_ctx; - if (frame != nullptr) - frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); - CompilerDeclContext frame_decl_context = frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext() : CompilerDeclContext(); - - // We can't do this without a compiler decl context for our frame. - if (frame_decl_context) - { - clang::DeclContext *frame_decl_ctx = (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext(); - ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(frame_decl_context.GetTypeSystem()); - - // Structure to hold the info needed when comparing function - // declarations. - struct FuncDeclInfo - { - ConstString m_name; - CompilerType m_copied_type; - uint32_t m_decl_lvl; - SymbolContext m_sym_ctx; - }; - - // First, symplify things by looping through the symbol contexts - // to remove unwanted functions and separate out the functions we - // want to compare and prune into a separate list. - // Cache the info needed about the function declarations in a - // vector for efficiency. - SymbolContextList sc_sym_list; - uint32_t num_indices = sc_list.GetSize(); - std::vector<FuncDeclInfo> fdi_cache; - fdi_cache.reserve(num_indices); - for (uint32_t index = 0; index < num_indices; ++index) - { - FuncDeclInfo fdi; - SymbolContext sym_ctx; - sc_list.GetContextAtIndex(index, sym_ctx); - - // We don't know enough about symbols to compare them, - // but we should keep them in the list. - Function *function = sym_ctx.function; - if (!function) - { - sc_sym_list.Append(sym_ctx); - continue; - } - // Filter out functions without declaration contexts, as well as - // class/instance methods, since they'll be skipped in the - // code that follows anyway. - CompilerDeclContext func_decl_context = function->GetDeclContext(); - if (!func_decl_context || func_decl_context.IsClassMethod(nullptr, nullptr, nullptr)) - continue; - // We can only prune functions for which we can copy the type. - CompilerType func_clang_type = function->GetType()->GetFullCompilerType(); - CompilerType copied_func_type = GuardedCopyType(func_clang_type); - if (!copied_func_type) - { - sc_sym_list.Append(sym_ctx); - continue; - } - - fdi.m_sym_ctx = sym_ctx; - fdi.m_name = function->GetName(); - fdi.m_copied_type = copied_func_type; - fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL; - if (fdi.m_copied_type && func_decl_context) - { - // Call CountDeclLevels to get the number of parent scopes we - // have to look through before we find the function declaration. - // When comparing functions of the same type, the one with a - // lower count will be closer to us in the lookup scope and - // shadows the other. - clang::DeclContext *func_decl_ctx = (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext(); - fdi.m_decl_lvl = ast->CountDeclLevels(frame_decl_ctx, - func_decl_ctx, - &fdi.m_name, - &fdi.m_copied_type); - } - fdi_cache.emplace_back(fdi); - } - - // Loop through the functions in our cache looking for matching types, - // then compare their scope levels to see which is closer. - std::multimap<CompilerType, const FuncDeclInfo*> matches; - for (const FuncDeclInfo &fdi : fdi_cache) - { - const CompilerType t = fdi.m_copied_type; - auto q = matches.find(t); - if (q != matches.end()) - { - if (q->second->m_decl_lvl > fdi.m_decl_lvl) - // This function is closer; remove the old set. - matches.erase(t); - else if (q->second->m_decl_lvl < fdi.m_decl_lvl) - // The functions in our set are closer - skip this one. - continue; - } - matches.insert(std::make_pair(t, &fdi)); - } - - // Loop through our matches and add their symbol contexts to our list. - SymbolContextList sc_func_list; - for (const auto &q : matches) - sc_func_list.Append(q.second->m_sym_ctx); - - // Rejoin the lists with the functions in front. - sc_list = sc_func_list; - sc_list.Append(sc_sym_list); - } - } + // Loop through our matches and add their symbol contexts to our list. + SymbolContextList sc_func_list; + for (const auto &q : matches) + sc_func_list.Append(q.second->m_sym_ctx); - if (sc_list.GetSize()) - { - Symbol *extern_symbol = NULL; - Symbol *non_extern_symbol = NULL; - - for (uint32_t index = 0, num_indices = sc_list.GetSize(); - index < num_indices; - ++index) - { - SymbolContext sym_ctx; - sc_list.GetContextAtIndex(index, sym_ctx); - - if (sym_ctx.function) - { - CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext(); - - if (!decl_ctx) - continue; - - // Filter out class/instance methods. - if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr)) - continue; - - AddOneFunction(context, sym_ctx.function, NULL, current_id); - context.m_found.function_with_type_info = true; - context.m_found.function = true; - } - else if (sym_ctx.symbol) - { - if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) - { - sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target); - if (sym_ctx.symbol == NULL) - continue; - } - - if (sym_ctx.symbol->IsExternal()) - extern_symbol = sym_ctx.symbol; - else - non_extern_symbol = sym_ctx.symbol; - } - } - - if (!context.m_found.function_with_type_info) - { - for (clang::NamedDecl *decl : decls_from_modules) - { - if (llvm::isa<clang::FunctionDecl>(decl)) - { - clang::NamedDecl *copied_decl = llvm::cast_or_null<FunctionDecl>(m_ast_importer_sp->CopyDecl(m_ast_context, &decl->getASTContext(), decl)); - if (copied_decl) - { - context.AddNamedDecl(copied_decl); - context.m_found.function_with_type_info = true; - } - } - } - } - - if (!context.m_found.function_with_type_info) - { - if (extern_symbol) - { - AddOneFunction (context, NULL, extern_symbol, current_id); - context.m_found.function = true; - } - else if (non_extern_symbol) - { - AddOneFunction (context, NULL, non_extern_symbol, current_id); - context.m_found.function = true; - } - } + // Rejoin the lists with the functions in front. + sc_list = sc_func_list; + sc_list.Append(sc_sym_list); + } + } + + if (sc_list.GetSize()) { + Symbol *extern_symbol = NULL; + Symbol *non_extern_symbol = NULL; + + for (uint32_t index = 0, num_indices = sc_list.GetSize(); + index < num_indices; ++index) { + SymbolContext sym_ctx; + sc_list.GetContextAtIndex(index, sym_ctx); + + if (sym_ctx.function) { + CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext(); + + if (!decl_ctx) + continue; + + // Filter out class/instance methods. + if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr)) + continue; + + AddOneFunction(context, sym_ctx.function, NULL, current_id); + context.m_found.function_with_type_info = true; + context.m_found.function = true; + } else if (sym_ctx.symbol) { + if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) { + sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target); + if (sym_ctx.symbol == NULL) + continue; } - - if (!context.m_found.function_with_type_info) - { - // Try the modules next. - - do - { - if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) - { - bool append = false; - uint32_t max_matches = 1; - std::vector <clang::NamedDecl *> decls; - - if (!modules_decl_vendor->FindDecls(name, - append, - max_matches, - decls)) - break; - - clang::NamedDecl *const decl_from_modules = decls[0]; - - if (llvm::isa<clang::FunctionDecl>(decl_from_modules)) - { - if (log) - { - log->Printf(" CAS::FEVD[%u] Matching function found for \"%s\" in the modules", - current_id, - name.GetCString()); - } - - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); - clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl) : nullptr; - - if (!copied_function_decl) - { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a function declaration from the modules", - current_id); - - break; - } - - MaybeRegisterFunctionBody(copied_function_decl); - - context.AddNamedDecl(copied_function_decl); - - context.m_found.function_with_type_info = true; - context.m_found.function = true; - } - else if (llvm::isa<clang::VarDecl>(decl_from_modules)) - { - if (log) - { - log->Printf(" CAS::FEVD[%u] Matching variable found for \"%s\" in the modules", - current_id, - name.GetCString()); - } - - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); - clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) : nullptr; - - if (!copied_var_decl) - { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a variable declaration from the modules", - current_id); - - break; - } - - context.AddNamedDecl(copied_var_decl); - - context.m_found.variable = true; - } - } - } while (0); + + if (sym_ctx.symbol->IsExternal()) + extern_symbol = sym_ctx.symbol; + else + non_extern_symbol = sym_ctx.symbol; + } + } + + if (!context.m_found.function_with_type_info) { + for (clang::NamedDecl *decl : decls_from_modules) { + if (llvm::isa<clang::FunctionDecl>(decl)) { + clang::NamedDecl *copied_decl = + llvm::cast_or_null<FunctionDecl>(m_ast_importer_sp->CopyDecl( + m_ast_context, &decl->getASTContext(), decl)); + if (copied_decl) { + context.AddNamedDecl(copied_decl); + context.m_found.function_with_type_info = true; + } } + } + } - if (target && !context.m_found.variable && !namespace_decl) - { - // We couldn't find a non-symbol variable for this. Now we'll hunt for a generic - // data symbol, and -- if it is found -- treat it as a variable. - - const Symbol *data_symbol = FindGlobalDataSymbol(*target, name); - - if (data_symbol) - { - std::string warning("got name from symbols: "); - warning.append(name.AsCString()); - const unsigned diag_id = m_ast_context->getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Level::Warning, "%0"); - m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str(); - AddOneGenericVariable(context, *data_symbol, current_id); - context.m_found.variable = true; - } + if (!context.m_found.function_with_type_info) { + if (extern_symbol) { + AddOneFunction(context, NULL, extern_symbol, current_id); + context.m_found.function = true; + } else if (non_extern_symbol) { + AddOneFunction(context, NULL, non_extern_symbol, current_id); + context.m_found.function = true; + } + } + } + + if (!context.m_found.function_with_type_info) { + // Try the modules next. + + do { + if (ClangModulesDeclVendor *modules_decl_vendor = + m_target->GetClangModulesDeclVendor()) { + bool append = false; + uint32_t max_matches = 1; + std::vector<clang::NamedDecl *> decls; + + if (!modules_decl_vendor->FindDecls(name, append, max_matches, + decls)) + break; + + clang::NamedDecl *const decl_from_modules = decls[0]; + + if (llvm::isa<clang::FunctionDecl>(decl_from_modules)) { + if (log) { + log->Printf(" CAS::FEVD[%u] Matching function found for " + "\"%s\" in the modules", + current_id, name.GetCString()); + } + + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( + m_ast_context, &decl_from_modules->getASTContext(), + decl_from_modules); + clang::FunctionDecl *copied_function_decl = + copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl) + : nullptr; + + if (!copied_function_decl) { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a function " + "declaration from the modules", + current_id); + + break; + } + + MaybeRegisterFunctionBody(copied_function_decl); + + context.AddNamedDecl(copied_function_decl); + + context.m_found.function_with_type_info = true; + context.m_found.function = true; + } else if (llvm::isa<clang::VarDecl>(decl_from_modules)) { + if (log) { + log->Printf(" CAS::FEVD[%u] Matching variable found for " + "\"%s\" in the modules", + current_id, name.GetCString()); + } + + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( + m_ast_context, &decl_from_modules->getASTContext(), + decl_from_modules); + clang::VarDecl *copied_var_decl = + copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) + : nullptr; + + if (!copied_var_decl) { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a variable " + "declaration from the modules", + current_id); + + break; + } + + context.AddNamedDecl(copied_var_decl); + + context.m_found.variable = true; } + } + } while (0); + } + + if (target && !context.m_found.variable && !namespace_decl) { + // We couldn't find a non-symbol variable for this. Now we'll hunt for + // a generic + // data symbol, and -- if it is found -- treat it as a variable. + + const Symbol *data_symbol = FindGlobalDataSymbol(*target, name); + + if (data_symbol) { + std::string warning("got name from symbols: "); + warning.append(name.AsCString()); + const unsigned diag_id = + m_ast_context->getDiagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Level::Warning, "%0"); + m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str(); + AddOneGenericVariable(context, *data_symbol, current_id); + context.m_found.variable = true; } + } } + } } -//static opaque_compiler_type_t -//MaybePromoteToBlockPointerType +// static opaque_compiler_type_t +// MaybePromoteToBlockPointerType //( // ASTContext *ast_context, // opaque_compiler_type_t candidate_type @@ -1647,14 +1562,16 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, // // QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type); // -// const PointerType *candidate_pointer_type = dyn_cast<PointerType>(candidate_qual_type); +// const PointerType *candidate_pointer_type = +// dyn_cast<PointerType>(candidate_qual_type); // // if (!candidate_pointer_type) // return candidate_type; // // QualType pointee_qual_type = candidate_pointer_type->getPointeeType(); // -// const RecordType *pointee_record_type = dyn_cast<RecordType>(pointee_qual_type); +// const RecordType *pointee_record_type = +// dyn_cast<RecordType>(pointee_qual_type); // // if (!pointee_record_type) // return candidate_type; @@ -1664,659 +1581,639 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, // if (!pointee_record_decl->isRecord()) // return candidate_type; // -// if (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_"))) +// if +// (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_"))) // return candidate_type; // -// QualType generic_function_type = ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy); -// QualType block_pointer_type = ast_context->getBlockPointerType(generic_function_type); +// QualType generic_function_type = +// ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy); +// QualType block_pointer_type = +// ast_context->getBlockPointerType(generic_function_type); // // return block_pointer_type.getAsOpaquePtr(); //} -bool -ClangExpressionDeclMap::GetVariableValue (VariableSP &var, - lldb_private::Value &var_location, - TypeFromUser *user_type, - TypeFromParser *parser_type) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - Type *var_type = var->GetType(); - - if (!var_type) - { - if (log) - log->PutCString("Skipped a definition because it has no type"); - return false; - } - - CompilerType var_clang_type = var_type->GetFullCompilerType (); +bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, + lldb_private::Value &var_location, + TypeFromUser *user_type, + TypeFromParser *parser_type) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (!var_clang_type) - { - if (log) - log->PutCString("Skipped a definition because it has no Clang type"); - return false; - } - - ClangASTContext *clang_ast = llvm::dyn_cast_or_null<ClangASTContext>(var_type->GetForwardCompilerType().GetTypeSystem()); - - if (!clang_ast) - { - if (log) - log->PutCString("Skipped a definition because it has no Clang AST"); - return false; - } + Type *var_type = var->GetType(); + if (!var_type) { + if (log) + log->PutCString("Skipped a definition because it has no type"); + return false; + } - ASTContext *ast = clang_ast->getASTContext(); + CompilerType var_clang_type = var_type->GetFullCompilerType(); - if (!ast) - { - if (log) - log->PutCString("There is no AST context for the current execution context"); - return false; - } - //var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type); + if (!var_clang_type) { + if (log) + log->PutCString("Skipped a definition because it has no Clang type"); + return false; + } - DWARFExpression &var_location_expr = var->LocationExpression(); + ClangASTContext *clang_ast = llvm::dyn_cast_or_null<ClangASTContext>( + var_type->GetForwardCompilerType().GetTypeSystem()); - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - Error err; + if (!clang_ast) { + if (log) + log->PutCString("Skipped a definition because it has no Clang AST"); + return false; + } - if (var->GetLocationIsConstantValueData()) - { - DataExtractor const_value_extractor; + ASTContext *ast = clang_ast->getASTContext(); - if (var_location_expr.GetExpressionData(const_value_extractor)) - { - var_location = Value(const_value_extractor.GetDataStart(), const_value_extractor.GetByteSize()); - var_location.SetValueType(Value::eValueTypeHostAddress); - } - else - { - if (log) - log->Printf("Error evaluating constant variable: %s", err.AsCString()); - return false; - } + if (!ast) { + if (log) + log->PutCString( + "There is no AST context for the current execution context"); + return false; + } + // var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type); + + DWARFExpression &var_location_expr = var->LocationExpression(); + + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + Error err; + + if (var->GetLocationIsConstantValueData()) { + DataExtractor const_value_extractor; + + if (var_location_expr.GetExpressionData(const_value_extractor)) { + var_location = Value(const_value_extractor.GetDataStart(), + const_value_extractor.GetByteSize()); + var_location.SetValueType(Value::eValueTypeHostAddress); + } else { + if (log) + log->Printf("Error evaluating constant variable: %s", err.AsCString()); + return false; } + } - CompilerType type_to_use = GuardedCopyType(var_clang_type); + CompilerType type_to_use = GuardedCopyType(var_clang_type); - if (!type_to_use) - { - if (log) - log->Printf("Couldn't copy a variable's type into the parser's AST context"); + if (!type_to_use) { + if (log) + log->Printf( + "Couldn't copy a variable's type into the parser's AST context"); - return false; - } + return false; + } - if (parser_type) - *parser_type = TypeFromParser(type_to_use); + if (parser_type) + *parser_type = TypeFromParser(type_to_use); - if (var_location.GetContextType() == Value::eContextTypeInvalid) - var_location.SetCompilerType(type_to_use); + if (var_location.GetContextType() == Value::eContextTypeInvalid) + var_location.SetCompilerType(type_to_use); - if (var_location.GetValueType() == Value::eValueTypeFileAddress) - { - SymbolContext var_sc; - var->CalculateSymbolContext(&var_sc); + if (var_location.GetValueType() == Value::eValueTypeFileAddress) { + SymbolContext var_sc; + var->CalculateSymbolContext(&var_sc); - if (!var_sc.module_sp) - return false; + if (!var_sc.module_sp) + return false; - Address so_addr(var_location.GetScalar().ULongLong(), var_sc.module_sp->GetSectionList()); + Address so_addr(var_location.GetScalar().ULongLong(), + var_sc.module_sp->GetSectionList()); - lldb::addr_t load_addr = so_addr.GetLoadAddress(target); + lldb::addr_t load_addr = so_addr.GetLoadAddress(target); - if (load_addr != LLDB_INVALID_ADDRESS) - { - var_location.GetScalar() = load_addr; - var_location.SetValueType(Value::eValueTypeLoadAddress); - } + if (load_addr != LLDB_INVALID_ADDRESS) { + var_location.GetScalar() = load_addr; + var_location.SetValueType(Value::eValueTypeLoadAddress); } + } - if (user_type) - *user_type = TypeFromUser(var_clang_type); + if (user_type) + *user_type = TypeFromUser(var_clang_type); - return true; + return true; } -void -ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP var, ValueObjectSP valobj, unsigned int current_id) -{ - assert (m_parser_vars.get()); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, + VariableSP var, + ValueObjectSP valobj, + unsigned int current_id) { + assert(m_parser_vars.get()); - TypeFromUser ut; - TypeFromParser pt; - Value var_location; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (!GetVariableValue (var, var_location, &ut, &pt)) - return; - - clang::QualType parser_opaque_type = QualType::getFromOpaquePtr(pt.GetOpaqueQualType()); - - if (parser_opaque_type.isNull()) - return; - - if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) - { - if (const TagType *tag_type = dyn_cast<TagType>(parser_type)) - CompleteType(tag_type->getDecl()); - if (const ObjCObjectPointerType *objc_object_ptr_type = dyn_cast<ObjCObjectPointerType>(parser_type)) - CompleteType(objc_object_ptr_type->getInterfaceDecl()); - } + TypeFromUser ut; + TypeFromParser pt; + Value var_location; + if (!GetVariableValue(var, var_location, &ut, &pt)) + return; - bool is_reference = pt.IsReferenceType(); - - NamedDecl *var_decl = NULL; - if (is_reference) - var_decl = context.AddVarDecl(pt); - else - var_decl = context.AddVarDecl(pt.GetLValueReferenceType()); - - std::string decl_name(context.m_decl_name.getAsString()); - ConstString entity_name(decl_name.c_str()); - ClangExpressionVariable *entity(new ClangExpressionVariable(valobj)); - m_found_entities.AddNewlyConstructedVariable(entity); - - assert (entity); - entity->EnableParserVars(GetParserID()); - ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); - parser_vars->m_parser_type = pt; - parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; - parser_vars->m_lldb_value = var_location; - parser_vars->m_lldb_var = var; + clang::QualType parser_opaque_type = + QualType::getFromOpaquePtr(pt.GetOpaqueQualType()); - if (is_reference) - entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; + if (parser_opaque_type.isNull()) + return; - if (log) - { - ASTDumper orig_dumper(ut.GetOpaqueQualType()); - ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", current_id, decl_name.c_str(), ast_dumper.GetCString(), orig_dumper.GetCString()); - } + if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) { + if (const TagType *tag_type = dyn_cast<TagType>(parser_type)) + CompleteType(tag_type->getDecl()); + if (const ObjCObjectPointerType *objc_object_ptr_type = + dyn_cast<ObjCObjectPointerType>(parser_type)) + CompleteType(objc_object_ptr_type->getInterfaceDecl()); + } + + bool is_reference = pt.IsReferenceType(); + + NamedDecl *var_decl = NULL; + if (is_reference) + var_decl = context.AddVarDecl(pt); + else + var_decl = context.AddVarDecl(pt.GetLValueReferenceType()); + + std::string decl_name(context.m_decl_name.getAsString()); + ConstString entity_name(decl_name.c_str()); + ClangExpressionVariable *entity(new ClangExpressionVariable(valobj)); + m_found_entities.AddNewlyConstructedVariable(entity); + + assert(entity); + entity->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = + entity->GetParserVars(GetParserID()); + parser_vars->m_parser_type = pt; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_value = var_location; + parser_vars->m_lldb_var = var; + + if (is_reference) + entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; + + if (log) { + ASTDumper orig_dumper(ut.GetOpaqueQualType()); + ASTDumper ast_dumper(var_decl); + log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", + current_id, decl_name.c_str(), ast_dumper.GetCString(), + orig_dumper.GetCString()); + } } -void -ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, - ExpressionVariableSP &pvar_sp, - unsigned int current_id) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - TypeFromUser user_type (llvm::cast<ClangExpressionVariable>(pvar_sp.get())->GetTypeFromUser()); - - TypeFromParser parser_type (GuardedCopyType(user_type)); - - if (!parser_type.GetOpaqueQualType()) - { - if (log) - log->Printf(" CEDM::FEVD[%u] Couldn't import type for pvar %s", current_id, pvar_sp->GetName().GetCString()); - return; - } +void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, + ExpressionVariableSP &pvar_sp, + unsigned int current_id) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - NamedDecl *var_decl = context.AddVarDecl(parser_type.GetLValueReferenceType()); + TypeFromUser user_type( + llvm::cast<ClangExpressionVariable>(pvar_sp.get())->GetTypeFromUser()); - llvm::cast<ClangExpressionVariable>(pvar_sp.get())->EnableParserVars(GetParserID()); - ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(pvar_sp.get())->GetParserVars(GetParserID()); - parser_vars->m_parser_type = parser_type; - parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; - parser_vars->m_lldb_value.Clear(); + TypeFromParser parser_type(GuardedCopyType(user_type)); + if (!parser_type.GetOpaqueQualType()) { if (log) - { - ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, pvar_sp->GetName().GetCString(), ast_dumper.GetCString()); - } + log->Printf(" CEDM::FEVD[%u] Couldn't import type for pvar %s", + current_id, pvar_sp->GetName().GetCString()); + return; + } + + NamedDecl *var_decl = + context.AddVarDecl(parser_type.GetLValueReferenceType()); + + llvm::cast<ClangExpressionVariable>(pvar_sp.get()) + ->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = + llvm::cast<ClangExpressionVariable>(pvar_sp.get()) + ->GetParserVars(GetParserID()); + parser_vars->m_parser_type = parser_type; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_value.Clear(); + + if (log) { + ASTDumper ast_dumper(var_decl); + log->Printf(" CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, + pvar_sp->GetName().GetCString(), ast_dumper.GetCString()); + } } -void -ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, - const Symbol &symbol, - unsigned int current_id) -{ - assert(m_parser_vars.get()); +void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, + const Symbol &symbol, + unsigned int current_id) { + assert(m_parser_vars.get()); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - if (target == NULL) - return; - - ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext(); - - TypeFromUser user_type (ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); - TypeFromParser parser_type (ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); - NamedDecl *var_decl = context.AddVarDecl(parser_type); - - std::string decl_name(context.m_decl_name.getAsString()); - ConstString entity_name(decl_name.c_str()); - ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (), - entity_name, - user_type, - m_parser_vars->m_target_info.byte_order, - m_parser_vars->m_target_info.address_byte_size)); - m_found_entities.AddNewlyConstructedVariable(entity); - - entity->EnableParserVars(GetParserID()); - ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); - - const Address symbol_address = symbol.GetAddress(); - lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target); - - //parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType()); - parser_vars->m_lldb_value.SetCompilerType(user_type); - parser_vars->m_lldb_value.GetScalar() = symbol_load_addr; - parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); - - parser_vars->m_parser_type = parser_type; - parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; - parser_vars->m_lldb_sym = &symbol; - - if (log) - { - ASTDumper ast_dumper(var_decl); + if (target == NULL) + return; - log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s", current_id, decl_name.c_str(), ast_dumper.GetCString()); - } + ASTContext *scratch_ast_context = + target->GetScratchClangASTContext()->getASTContext(); + + TypeFromUser user_type( + ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid) + .GetPointerType() + .GetLValueReferenceType()); + TypeFromParser parser_type( + ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid) + .GetPointerType() + .GetLValueReferenceType()); + NamedDecl *var_decl = context.AddVarDecl(parser_type); + + std::string decl_name(context.m_decl_name.getAsString()); + ConstString entity_name(decl_name.c_str()); + ClangExpressionVariable *entity(new ClangExpressionVariable( + m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), entity_name, + user_type, m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size)); + m_found_entities.AddNewlyConstructedVariable(entity); + + entity->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = + entity->GetParserVars(GetParserID()); + + const Address symbol_address = symbol.GetAddress(); + lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target); + + // parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, + // user_type.GetOpaqueQualType()); + parser_vars->m_lldb_value.SetCompilerType(user_type); + parser_vars->m_lldb_value.GetScalar() = symbol_load_addr; + parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); + + parser_vars->m_parser_type = parser_type; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_sym = &symbol; + + if (log) { + ASTDumper ast_dumper(var_decl); + + log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s", current_id, + decl_name.c_str(), ast_dumper.GetCString()); + } } -bool -ClangExpressionDeclMap::ResolveUnknownTypes() -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); +bool ClangExpressionDeclMap::ResolveUnknownTypes() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - ClangASTContext *scratch_ast_context = target->GetScratchClangASTContext(); + ClangASTContext *scratch_ast_context = target->GetScratchClangASTContext(); - for (size_t index = 0, num_entities = m_found_entities.GetSize(); - index < num_entities; - ++index) - { - ExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index); + for (size_t index = 0, num_entities = m_found_entities.GetSize(); + index < num_entities; ++index) { + ExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index); - ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(entity.get())->GetParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = + llvm::cast<ClangExpressionVariable>(entity.get()) + ->GetParserVars(GetParserID()); - if (entity->m_flags & ClangExpressionVariable::EVUnknownType) - { - const NamedDecl *named_decl = parser_vars->m_named_decl; - const VarDecl *var_decl = dyn_cast<VarDecl>(named_decl); + if (entity->m_flags & ClangExpressionVariable::EVUnknownType) { + const NamedDecl *named_decl = parser_vars->m_named_decl; + const VarDecl *var_decl = dyn_cast<VarDecl>(named_decl); - if (!var_decl) - { - if (log) - log->Printf("Entity of unknown type does not have a VarDecl"); - return false; - } + if (!var_decl) { + if (log) + log->Printf("Entity of unknown type does not have a VarDecl"); + return false; + } - if (log) - { - ASTDumper ast_dumper(const_cast<VarDecl*>(var_decl)); - log->Printf("Variable of unknown type now has Decl %s", ast_dumper.GetCString()); - } + if (log) { + ASTDumper ast_dumper(const_cast<VarDecl *>(var_decl)); + log->Printf("Variable of unknown type now has Decl %s", + ast_dumper.GetCString()); + } - QualType var_type = var_decl->getType(); - TypeFromParser parser_type(var_type.getAsOpaquePtr(), ClangASTContext::GetASTContext(&var_decl->getASTContext())); + QualType var_type = var_decl->getType(); + TypeFromParser parser_type( + var_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&var_decl->getASTContext())); - lldb::opaque_compiler_type_t copied_type = m_ast_importer_sp->CopyType(scratch_ast_context->getASTContext(), &var_decl->getASTContext(), var_type.getAsOpaquePtr()); + lldb::opaque_compiler_type_t copied_type = m_ast_importer_sp->CopyType( + scratch_ast_context->getASTContext(), &var_decl->getASTContext(), + var_type.getAsOpaquePtr()); - if (!copied_type) - { - if (log) - log->Printf("ClangExpressionDeclMap::ResolveUnknownType - Couldn't import the type for a variable"); + if (!copied_type) { + if (log) + log->Printf("ClangExpressionDeclMap::ResolveUnknownType - Couldn't " + "import the type for a variable"); - return (bool) lldb::ExpressionVariableSP(); - } + return (bool)lldb::ExpressionVariableSP(); + } - TypeFromUser user_type(copied_type, scratch_ast_context); + TypeFromUser user_type(copied_type, scratch_ast_context); -// parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType()); - parser_vars->m_lldb_value.SetCompilerType(user_type); - parser_vars->m_parser_type = parser_type; + // parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, + // user_type.GetOpaqueQualType()); + parser_vars->m_lldb_value.SetCompilerType(user_type); + parser_vars->m_parser_type = parser_type; - entity->SetCompilerType(user_type); + entity->SetCompilerType(user_type); - entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType); - } + entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType); } + } - return true; + return true; } -void -ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context, - const RegisterInfo *reg_info, - unsigned int current_id) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - CompilerType clang_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (m_ast_context, - reg_info->encoding, - reg_info->byte_size * 8); - - if (!clang_type) - { - if (log) - log->Printf(" Tried to add a type for %s, but couldn't get one", context.m_decl_name.getAsString().c_str()); - return; - } - - TypeFromParser parser_clang_type (clang_type); - - NamedDecl *var_decl = context.AddVarDecl(parser_clang_type); - - ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), - m_parser_vars->m_target_info.byte_order, - m_parser_vars->m_target_info.address_byte_size)); - m_found_entities.AddNewlyConstructedVariable(entity); +void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context, + const RegisterInfo *reg_info, + unsigned int current_id) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - std::string decl_name(context.m_decl_name.getAsString()); - entity->SetName (ConstString (decl_name.c_str())); - entity->SetRegisterInfo (reg_info); - entity->EnableParserVars(GetParserID()); - ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); - parser_vars->m_parser_type = parser_clang_type; - parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; - parser_vars->m_lldb_value.Clear(); - entity->m_flags |= ClangExpressionVariable::EVBareRegister; + CompilerType clang_type = + ClangASTContext::GetBuiltinTypeForEncodingAndBitSize( + m_ast_context, reg_info->encoding, reg_info->byte_size * 8); + if (!clang_type) { if (log) - { - ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%d] Added register %s, returned %s", current_id, context.m_decl_name.getAsString().c_str(), ast_dumper.GetCString()); - } + log->Printf(" Tried to add a type for %s, but couldn't get one", + context.m_decl_name.getAsString().c_str()); + return; + } + + TypeFromParser parser_clang_type(clang_type); + + NamedDecl *var_decl = context.AddVarDecl(parser_clang_type); + + ClangExpressionVariable *entity(new ClangExpressionVariable( + m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size)); + m_found_entities.AddNewlyConstructedVariable(entity); + + std::string decl_name(context.m_decl_name.getAsString()); + entity->SetName(ConstString(decl_name.c_str())); + entity->SetRegisterInfo(reg_info); + entity->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = + entity->GetParserVars(GetParserID()); + parser_vars->m_parser_type = parser_clang_type; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_value.Clear(); + entity->m_flags |= ClangExpressionVariable::EVBareRegister; + + if (log) { + ASTDumper ast_dumper(var_decl); + log->Printf(" CEDM::FEVD[%d] Added register %s, returned %s", current_id, + context.m_decl_name.getAsString().c_str(), + ast_dumper.GetCString()); + } } -void -ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, - Function* function, - Symbol* symbol, - unsigned int current_id) -{ - assert (m_parser_vars.get()); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - NamedDecl *function_decl = NULL; - Address fun_address; - CompilerType function_clang_type; - - bool is_indirect_function = false; - - if (function) - { - Type *function_type = function->GetType(); - - const lldb::LanguageType comp_unit_language = function->GetCompileUnit()->GetLanguage(); - const bool extern_c = Language::LanguageIsC(comp_unit_language) || - (Language::LanguageIsObjC(comp_unit_language) && - !Language::LanguageIsCPlusPlus(comp_unit_language)); - - if (!extern_c) - { - TypeSystem *type_system = function->GetDeclContext().GetTypeSystem(); - if (ClangASTContext *src_ast = llvm::dyn_cast<ClangASTContext>(type_system)) - { - clang::DeclContext *src_decl_context = (clang::DeclContext*)function->GetDeclContext().GetOpaqueDeclContext(); - clang::FunctionDecl *src_function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>(src_decl_context); - - if (src_function_decl) - { - if (clang::FunctionDecl *copied_function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>(m_ast_importer_sp->CopyDecl(m_ast_context, src_ast->getASTContext(), src_function_decl))) - { - if (log) - { - ASTDumper ast_dumper((clang::Decl*)copied_function_decl); - - StreamString ss; - - function->DumpSymbolContext(&ss); - - log->Printf(" CEDM::FEVD[%u] Imported decl for function %s (description %s), returned %s", - current_id, copied_function_decl->getNameAsString().c_str(), ss.GetData(), - ast_dumper.GetCString()); - } - - context.AddNamedDecl(copied_function_decl); - return; - } - else - { - if (log) - { - log->Printf (" Failed to import the function decl for '%s'", - src_function_decl->getName().str().c_str()); - } - } - } +void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, + Function *function, Symbol *symbol, + unsigned int current_id) { + assert(m_parser_vars.get()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + NamedDecl *function_decl = NULL; + Address fun_address; + CompilerType function_clang_type; + + bool is_indirect_function = false; + + if (function) { + Type *function_type = function->GetType(); + + const lldb::LanguageType comp_unit_language = + function->GetCompileUnit()->GetLanguage(); + const bool extern_c = Language::LanguageIsC(comp_unit_language) || + (Language::LanguageIsObjC(comp_unit_language) && + !Language::LanguageIsCPlusPlus(comp_unit_language)); + + if (!extern_c) { + TypeSystem *type_system = function->GetDeclContext().GetTypeSystem(); + if (ClangASTContext *src_ast = + llvm::dyn_cast<ClangASTContext>(type_system)) { + clang::DeclContext *src_decl_context = + (clang::DeclContext *)function->GetDeclContext() + .GetOpaqueDeclContext(); + clang::FunctionDecl *src_function_decl = + llvm::dyn_cast_or_null<clang::FunctionDecl>(src_decl_context); + + if (src_function_decl) { + if (clang::FunctionDecl *copied_function_decl = + llvm::dyn_cast_or_null<clang::FunctionDecl>( + m_ast_importer_sp->CopyDecl(m_ast_context, + src_ast->getASTContext(), + src_function_decl))) { + if (log) { + ASTDumper ast_dumper((clang::Decl *)copied_function_decl); + + StreamString ss; + + function->DumpSymbolContext(&ss); + + log->Printf(" CEDM::FEVD[%u] Imported decl for function %s " + "(description %s), returned %s", + current_id, + copied_function_decl->getNameAsString().c_str(), + ss.GetData(), ast_dumper.GetCString()); } - } - if (!function_type) - { - if (log) - log->PutCString(" Skipped a function because it has no type"); + context.AddNamedDecl(copied_function_decl); return; + } else { + if (log) { + log->Printf(" Failed to import the function decl for '%s'", + src_function_decl->getName().str().c_str()); + } + } } + } + } - function_clang_type = function_type->GetFullCompilerType (); + if (!function_type) { + if (log) + log->PutCString(" Skipped a function because it has no type"); + return; + } - if (!function_clang_type) - { - if (log) - log->PutCString(" Skipped a function because it has no Clang type"); - return; - } + function_clang_type = function_type->GetFullCompilerType(); - fun_address = function->GetAddressRange().GetBaseAddress(); + if (!function_clang_type) { + if (log) + log->PutCString(" Skipped a function because it has no Clang type"); + return; + } - CompilerType copied_function_type = GuardedCopyType(function_clang_type); - if (copied_function_type) - { - function_decl = context.AddFunDecl(copied_function_type, extern_c); + fun_address = function->GetAddressRange().GetBaseAddress(); - if (!function_decl) - { - if (log) - { - log->Printf (" Failed to create a function decl for '%s' {0x%8.8" PRIx64 "}", - function_type->GetName().GetCString(), - function_type->GetID()); - } + CompilerType copied_function_type = GuardedCopyType(function_clang_type); + if (copied_function_type) { + function_decl = context.AddFunDecl(copied_function_type, extern_c); - return; - } + if (!function_decl) { + if (log) { + log->Printf( + " Failed to create a function decl for '%s' {0x%8.8" PRIx64 "}", + function_type->GetName().GetCString(), function_type->GetID()); } - else - { - // We failed to copy the type we found - if (log) - { - log->Printf (" Failed to import the function type '%s' {0x%8.8" PRIx64 "} into the expression parser AST contenxt", - function_type->GetName().GetCString(), - function_type->GetID()); - } - return; - } - } - else if (symbol) - { - fun_address = symbol->GetAddress(); - function_decl = context.AddGenericFunDecl(); - is_indirect_function = symbol->IsIndirect(); - } - else - { - if (log) - log->PutCString(" AddOneFunction called with no function and no symbol"); return; + } + } else { + // We failed to copy the type we found + if (log) { + log->Printf(" Failed to import the function type '%s' {0x%8.8" PRIx64 + "} into the expression parser AST contenxt", + function_type->GetName().GetCString(), + function_type->GetID()); + } + + return; } + } else if (symbol) { + fun_address = symbol->GetAddress(); + function_decl = context.AddGenericFunDecl(); + is_indirect_function = symbol->IsIndirect(); + } else { + if (log) + log->PutCString(" AddOneFunction called with no function and no symbol"); + return; + } - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - - lldb::addr_t load_addr = fun_address.GetCallableLoadAddress(target, is_indirect_function); + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - ClangExpressionVariable *entity(new ClangExpressionVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (), - m_parser_vars->m_target_info.byte_order, - m_parser_vars->m_target_info.address_byte_size)); - m_found_entities.AddNewlyConstructedVariable(entity); + lldb::addr_t load_addr = + fun_address.GetCallableLoadAddress(target, is_indirect_function); - std::string decl_name(context.m_decl_name.getAsString()); - entity->SetName(ConstString(decl_name.c_str())); - entity->SetCompilerType (function_clang_type); - entity->EnableParserVars(GetParserID()); + ClangExpressionVariable *entity(new ClangExpressionVariable( + m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size)); + m_found_entities.AddNewlyConstructedVariable(entity); - ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + std::string decl_name(context.m_decl_name.getAsString()); + entity->SetName(ConstString(decl_name.c_str())); + entity->SetCompilerType(function_clang_type); + entity->EnableParserVars(GetParserID()); - if (load_addr != LLDB_INVALID_ADDRESS) - { - parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); - parser_vars->m_lldb_value.GetScalar() = load_addr; - } - else - { - // We have to try finding a file address. + ClangExpressionVariable::ParserVars *parser_vars = + entity->GetParserVars(GetParserID()); - lldb::addr_t file_addr = fun_address.GetFileAddress(); + if (load_addr != LLDB_INVALID_ADDRESS) { + parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); + parser_vars->m_lldb_value.GetScalar() = load_addr; + } else { + // We have to try finding a file address. - parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress); - parser_vars->m_lldb_value.GetScalar() = file_addr; - } + lldb::addr_t file_addr = fun_address.GetFileAddress(); + parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress); + parser_vars->m_lldb_value.GetScalar() = file_addr; + } - parser_vars->m_named_decl = function_decl; - parser_vars->m_llvm_value = NULL; + parser_vars->m_named_decl = function_decl; + parser_vars->m_llvm_value = NULL; - if (log) - { - ASTDumper ast_dumper(function_decl); + if (log) { + ASTDumper ast_dumper(function_decl); - StreamString ss; + StreamString ss; - fun_address.Dump(&ss, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); + fun_address.Dump(&ss, + m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), + Address::DumpStyleResolvedDescription); - log->Printf(" CEDM::FEVD[%u] Found %s function %s (description %s), returned %s", - current_id, - (function ? "specific" : "generic"), - decl_name.c_str(), - ss.GetData(), - ast_dumper.GetCString()); - } + log->Printf( + " CEDM::FEVD[%u] Found %s function %s (description %s), returned %s", + current_id, (function ? "specific" : "generic"), decl_name.c_str(), + ss.GetData(), ast_dumper.GetCString()); + } } -void -ClangExpressionDeclMap::AddThisType(NameSearchContext &context, - TypeFromUser &ut, - unsigned int current_id) -{ - CompilerType copied_clang_type = GuardedCopyType(ut); +void ClangExpressionDeclMap::AddThisType(NameSearchContext &context, + TypeFromUser &ut, + unsigned int current_id) { + CompilerType copied_clang_type = GuardedCopyType(ut); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (!copied_clang_type) - { - if (log) - log->Printf("ClangExpressionDeclMap::AddThisType - Couldn't import the type"); + if (!copied_clang_type) { + if (log) + log->Printf( + "ClangExpressionDeclMap::AddThisType - Couldn't import the type"); - return; + return; + } + + if (copied_clang_type.IsAggregateType() && + copied_clang_type.GetCompleteType()) { + CompilerType void_clang_type = + ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid); + CompilerType void_ptr_clang_type = void_clang_type.GetPointerType(); + + CompilerType method_type = ClangASTContext::CreateFunctionType( + m_ast_context, void_clang_type, &void_ptr_clang_type, 1, false, 0); + + const bool is_virtual = false; + const bool is_static = false; + const bool is_inline = false; + const bool is_explicit = false; + const bool is_attr_used = true; + const bool is_artificial = false; + + CXXMethodDecl *method_decl = + ClangASTContext::GetASTContext(m_ast_context) + ->AddMethodToCXXRecordType( + copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", + method_type, lldb::eAccessPublic, is_virtual, is_static, + is_inline, is_explicit, is_attr_used, is_artificial); + + if (log) { + ASTDumper method_ast_dumper((clang::Decl *)method_decl); + ASTDumper type_ast_dumper(copied_clang_type); + + log->Printf(" CEDM::AddThisType Added function $__lldb_expr " + "(description %s) for this type %s", + method_ast_dumper.GetCString(), type_ast_dumper.GetCString()); } + } - if (copied_clang_type.IsAggregateType() && copied_clang_type.GetCompleteType ()) - { - CompilerType void_clang_type = ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid); - CompilerType void_ptr_clang_type = void_clang_type.GetPointerType(); - - CompilerType method_type = ClangASTContext::CreateFunctionType (m_ast_context, - void_clang_type, - &void_ptr_clang_type, - 1, - false, - 0); - - const bool is_virtual = false; - const bool is_static = false; - const bool is_inline = false; - const bool is_explicit = false; - const bool is_attr_used = true; - const bool is_artificial = false; - - CXXMethodDecl *method_decl = ClangASTContext::GetASTContext(m_ast_context)-> - AddMethodToCXXRecordType (copied_clang_type.GetOpaqueQualType(), - "$__lldb_expr", - method_type, - lldb::eAccessPublic, - is_virtual, - is_static, - is_inline, - is_explicit, - is_attr_used, - is_artificial); - - if (log) - { - ASTDumper method_ast_dumper((clang::Decl*)method_decl); - ASTDumper type_ast_dumper(copied_clang_type); - - log->Printf(" CEDM::AddThisType Added function $__lldb_expr (description %s) for this type %s", - method_ast_dumper.GetCString(), - type_ast_dumper.GetCString()); - } - } + if (!copied_clang_type.IsValid()) + return; - if (!copied_clang_type.IsValid()) - return; - - TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo(QualType::getFromOpaquePtr(copied_clang_type.GetOpaqueQualType())); - - if (!type_source_info) - return; - - // Construct a typedef type because if "*this" is a templated type we can't just return ClassTemplateSpecializationDecls in response to name queries. - // Using a typedef makes this much more robust. - - TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context, - m_ast_context->getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - context.m_decl_name.getAsIdentifierInfo(), - type_source_info); - - - if (!typedef_decl) - return; - - context.AddNamedDecl(typedef_decl); + TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo( + QualType::getFromOpaquePtr(copied_clang_type.GetOpaqueQualType())); + if (!type_source_info) return; + + // Construct a typedef type because if "*this" is a templated type we can't + // just return ClassTemplateSpecializationDecls in response to name queries. + // Using a typedef makes this much more robust. + + TypedefDecl *typedef_decl = TypedefDecl::Create( + *m_ast_context, m_ast_context->getTranslationUnitDecl(), SourceLocation(), + SourceLocation(), context.m_decl_name.getAsIdentifierInfo(), + type_source_info); + + if (!typedef_decl) + return; + + context.AddNamedDecl(typedef_decl); + + return; } -void -ClangExpressionDeclMap::AddOneType(NameSearchContext &context, - TypeFromUser &ut, - unsigned int current_id) -{ - CompilerType copied_clang_type = GuardedCopyType(ut); +void ClangExpressionDeclMap::AddOneType(NameSearchContext &context, + TypeFromUser &ut, + unsigned int current_id) { + CompilerType copied_clang_type = GuardedCopyType(ut); - if (!copied_clang_type) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (!copied_clang_type) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type"); + if (log) + log->Printf( + "ClangExpressionDeclMap::AddOneType - Couldn't import the type"); - return; - } + return; + } - context.AddTypeDecl(copied_clang_type); + context.AddTypeDecl(copied_clang_type); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index 537db71cfeb..ab15d330539 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -17,37 +17,40 @@ // C++ Includes #include <vector> -#include "ClangExpressionVariable.h" #include "ClangASTSource.h" +#include "ClangExpressionVariable.h" // Other libraries and framework includes // Project includes -#include "llvm/ADT/DenseMap.h" -#include "clang/AST/Decl.h" -#include "lldb/lldb-public.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/Value.h" #include "lldb/Expression/Materializer.h" -#include "lldb/Symbol/TaggedASTType.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/TaggedASTType.h" #include "lldb/Target/ExecutionContext.h" +#include "lldb/lldb-public.h" +#include "clang/AST/Decl.h" +#include "llvm/ADT/DenseMap.h" namespace lldb_private { //---------------------------------------------------------------------- -/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h "lldb/Expression/ClangExpressionDeclMap.h" +/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h +/// "lldb/Expression/ClangExpressionDeclMap.h" /// @brief Manages named entities that are defined in LLDB's debug information. /// /// The Clang parser uses the ClangASTSource as an interface to request named -/// entities from outside an expression. The ClangASTSource reports back, listing +/// entities from outside an expression. The ClangASTSource reports back, +/// listing /// all possible objects corresponding to a particular name. But it in turn -/// relies on ClangExpressionDeclMap, which performs several important functions. +/// relies on ClangExpressionDeclMap, which performs several important +/// functions. /// /// First, it records what variables and functions were looked up and what Decls /// were returned for them. /// -/// Second, it constructs a struct on behalf of IRForTarget, recording which -/// variables should be placed where and relaying this information back so that +/// Second, it constructs a struct on behalf of IRForTarget, recording which +/// variables should be placed where and relaying this information back so that /// IRForTarget can generate context-independent code. /// /// Third, it "materializes" this struct on behalf of the expression command, @@ -57,642 +60,581 @@ namespace lldb_private { /// Fourth and finally, it "dematerializes" the struct after the JITted code has /// has executed, placing the new values back where it found the old ones. //---------------------------------------------------------------------- -class ClangExpressionDeclMap : - public ClangASTSource -{ +class ClangExpressionDeclMap : public ClangASTSource { public: - //------------------------------------------------------------------ - /// Constructor - /// - /// Initializes class variables. - /// - /// @param[in] keep_result_in_memory - /// If true, inhibits the normal deallocation of the memory for - /// the result persistent variable, and instead marks the variable - /// as persisting. - /// - /// @param[in] delegate - /// If non-NULL, use this delegate to report result values. This - /// allows the client ClangUserExpression to report a result. - /// - /// @param[in] exe_ctx - /// The execution context to use when parsing. - //------------------------------------------------------------------ - ClangExpressionDeclMap (bool keep_result_in_memory, - Materializer::PersistentVariableDelegate *result_delegate, - ExecutionContext &exe_ctx); - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - ~ClangExpressionDeclMap() override; - - //------------------------------------------------------------------ - /// Enable the state needed for parsing and IR transformation. - /// - /// @param[in] exe_ctx - /// The execution context to use when finding types for variables. - /// Also used to find a "scratch" AST context to store result types. - /// - /// @param[in] materializer - /// If non-NULL, the materializer to populate with information about - /// the variables to use - /// - /// @return - /// True if parsing is possible; false if it is unsafe to continue. - //------------------------------------------------------------------ - bool - WillParse (ExecutionContext &exe_ctx, - Materializer *materializer); - - void - InstallCodeGenerator (clang::ASTConsumer *code_gen); - - //------------------------------------------------------------------ - /// [Used by ClangExpressionParser] For each variable that had an unknown - /// type at the beginning of parsing, determine its final type now. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - ResolveUnknownTypes(); - - //------------------------------------------------------------------ - /// Disable the state needed for parsing and IR transformation. - //------------------------------------------------------------------ - void - DidParse (); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Add a variable to the list of persistent - /// variables for the process. - /// - /// @param[in] decl - /// The Clang declaration for the persistent variable, used for - /// lookup during parsing. - /// - /// @param[in] name - /// The name of the persistent variable, usually $something. - /// - /// @param[in] type - /// The type of the variable, in the Clang parser's context. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - AddPersistentVariable (const clang::NamedDecl *decl, - const ConstString &name, - TypeFromParser type, - bool is_result, - bool is_lvalue); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Add a variable to the struct that needs to - /// be materialized each time the expression runs. - /// - /// @param[in] decl - /// The Clang declaration for the variable. - /// - /// @param[in] name - /// The name of the variable. - /// - /// @param[in] value - /// The LLVM IR value for this variable. - /// - /// @param[in] size - /// The size of the variable in bytes. - /// - /// @param[in] alignment - /// The required alignment of the variable in bytes. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - AddValueToStruct (const clang::NamedDecl *decl, - const ConstString &name, - llvm::Value *value, - size_t size, - lldb::offset_t alignment); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Finalize the struct, laying out the position - /// of each object in it. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - DoStructLayout (); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Get general information about the laid-out - /// struct after DoStructLayout() has been called. - /// - /// @param[out] num_elements - /// The number of elements in the struct. - /// - /// @param[out] size - /// The size of the struct, in bytes. - /// - /// @param[out] alignment - /// The alignment of the struct, in bytes. - /// - /// @return - /// True if the information could be retrieved; false otherwise. - //------------------------------------------------------------------ - bool - GetStructInfo (uint32_t &num_elements, - size_t &size, - lldb::offset_t &alignment); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Get specific information about one field - /// of the laid-out struct after DoStructLayout() has been called. - /// - /// @param[out] decl - /// The parsed Decl for the field, as generated by ClangASTSource - /// on ClangExpressionDeclMap's behalf. In the case of the result - /// value, this will have the name $__lldb_result even if the - /// result value ends up having the name $1. This is an - /// implementation detail of IRForTarget. - /// - /// @param[out] value - /// The IR value for the field (usually a GlobalVariable). In - /// the case of the result value, this will have the correct - /// name ($1, for instance). This is an implementation detail - /// of IRForTarget. - /// - /// @param[out] offset - /// The offset of the field from the beginning of the struct. - /// As long as the struct is aligned according to its required - /// alignment, this offset will align the field correctly. - /// - /// @param[out] name - /// The name of the field as used in materialization. - /// - /// @param[in] index - /// The index of the field about which information is requested. - /// - /// @return - /// True if the information could be retrieved; false otherwise. - //------------------------------------------------------------------ - bool - GetStructElement (const clang::NamedDecl *&decl, - llvm::Value *&value, - lldb::offset_t &offset, - ConstString &name, - uint32_t index); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Get information about a function given its - /// Decl. - /// - /// @param[in] decl - /// The parsed Decl for the Function, as generated by ClangASTSource - /// on ClangExpressionDeclMap's behalf. - /// - /// @param[out] ptr - /// The absolute address of the function in the target. - /// - /// @return - /// True if the information could be retrieved; false otherwise. - //------------------------------------------------------------------ - bool - GetFunctionInfo (const clang::NamedDecl *decl, - uint64_t &ptr); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Get the address of a symbol given nothing - /// but its name. - /// - /// @param[in] target - /// The target to find the symbol in. If not provided, - /// then the current parsing context's Target. - /// - /// @param[in] process - /// The process to use. For Objective-C symbols, the process's - /// Objective-C language runtime may be queried if the process - /// is non-NULL. - /// - /// @param[in] name - /// The name of the symbol. - /// - /// @param[in] module - /// The module to limit the search to. This can be NULL - /// - /// @return - /// Valid load address for the symbol - //------------------------------------------------------------------ - lldb::addr_t - GetSymbolAddress (Target &target, - Process *process, - const ConstString &name, - lldb::SymbolType symbol_type, - Module *module = NULL); - - lldb::addr_t - GetSymbolAddress (const ConstString &name, - lldb::SymbolType symbol_type); - - //------------------------------------------------------------------ - /// [Used by IRInterpreter] Get basic target information. - /// - /// @param[out] byte_order - /// The byte order of the target. - /// - /// @param[out] address_byte_size - /// The size of a pointer in bytes. - /// - /// @return - /// True if the information could be determined; false - /// otherwise. - //------------------------------------------------------------------ - struct TargetInfo - { - lldb::ByteOrder byte_order; - size_t address_byte_size; - - TargetInfo() : - byte_order(lldb::eByteOrderInvalid), - address_byte_size(0) - { - } - - bool IsValid() - { - return (byte_order != lldb::eByteOrderInvalid && - address_byte_size != 0); - } - }; - TargetInfo GetTargetInfo(); - - //------------------------------------------------------------------ - /// [Used by ClangASTSource] Find all entities matching a given name, - /// using a NameSearchContext to make Decls for them. - /// - /// @param[in] context - /// The NameSearchContext that can construct Decls for this name. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - void - FindExternalVisibleDecls(NameSearchContext &context) override; - - //------------------------------------------------------------------ - /// Find all entities matching a given name in a given module/namespace, - /// using a NameSearchContext to make Decls for them. - /// - /// @param[in] context - /// The NameSearchContext that can construct Decls for this name. - /// - /// @param[in] module - /// If non-NULL, the module to query. - /// - /// @param[in] namespace_decl - /// If valid and module is non-NULL, the parent namespace. - /// - /// @param[in] name - /// The name as a plain C string. The NameSearchContext contains - /// a DeclarationName for the name so at first the name may seem - /// redundant, but ClangExpressionDeclMap operates in RTTI land so - /// it can't access DeclarationName. - /// - /// @param[in] current_id - /// The ID for the current FindExternalVisibleDecls invocation, - /// for logging purposes. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - void - FindExternalVisibleDecls (NameSearchContext &context, - lldb::ModuleSP module, - CompilerDeclContext &namespace_decl, - unsigned int current_id); -private: - ExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser. - ExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct. - bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory. - Materializer::PersistentVariableDelegate *m_result_delegate; ///< If non-NULL, used to report expression results to ClangUserExpression. - - //---------------------------------------------------------------------- - /// The following values should not live beyond parsing - //---------------------------------------------------------------------- - class ParserVars - { - public: - ParserVars(ClangExpressionDeclMap &decl_map) : - m_decl_map(decl_map) - { - } - - Target * - GetTarget() - { - if (m_exe_ctx.GetTargetPtr()) - return m_exe_ctx.GetTargetPtr(); - else if (m_sym_ctx.target_sp) - m_sym_ctx.target_sp.get(); - return NULL; - } - - ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. - SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types. - ClangPersistentVariables *m_persistent_vars = nullptr; ///< The persistent variables for the process. - bool m_enable_lookups = false; ///< Set to true during parsing if we have found the first "$__lldb" name. - TargetInfo m_target_info; ///< Basic information about the target. - Materializer *m_materializer = nullptr; ///< If non-NULL, the materializer to use when reporting used variables. - clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator that receives new top-level functions. - private: - ClangExpressionDeclMap &m_decl_map; - DISALLOW_COPY_AND_ASSIGN (ParserVars); - }; - - std::unique_ptr<ParserVars> m_parser_vars; - - //---------------------------------------------------------------------- - /// Activate parser-specific variables - //---------------------------------------------------------------------- - void - EnableParserVars() - { - if (!m_parser_vars.get()) - m_parser_vars.reset(new ParserVars(*this)); - } - - //---------------------------------------------------------------------- - /// Deallocate parser-specific variables - //---------------------------------------------------------------------- - void - DisableParserVars() - { - m_parser_vars.reset(); - } - - //---------------------------------------------------------------------- - /// The following values contain layout information for the materialized - /// struct, but are not specific to a single materialization - //---------------------------------------------------------------------- - struct StructVars { - StructVars() : - m_struct_alignment(0), - m_struct_size(0), - m_struct_laid_out(false), - m_result_name(), - m_object_pointer_type(NULL, NULL) - { - } - - lldb::offset_t m_struct_alignment; ///< The alignment of the struct in bytes. - size_t m_struct_size; ///< The size of the struct in bytes. - bool m_struct_laid_out; ///< True if the struct has been laid out and the layout is valid (that is, no new fields have been added since). - ConstString m_result_name; ///< The name of the result variable ($1, for example) - TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if one exists - }; - - std::unique_ptr<StructVars> m_struct_vars; - - //---------------------------------------------------------------------- - /// Activate struct variables - //---------------------------------------------------------------------- - void - EnableStructVars() - { - if (!m_struct_vars.get()) - m_struct_vars.reset(new struct StructVars); - } - - //---------------------------------------------------------------------- - /// Deallocate struct variables - //---------------------------------------------------------------------- - void - DisableStructVars() - { - m_struct_vars.reset(); + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] keep_result_in_memory + /// If true, inhibits the normal deallocation of the memory for + /// the result persistent variable, and instead marks the variable + /// as persisting. + /// + /// @param[in] delegate + /// If non-NULL, use this delegate to report result values. This + /// allows the client ClangUserExpression to report a result. + /// + /// @param[in] exe_ctx + /// The execution context to use when parsing. + //------------------------------------------------------------------ + ClangExpressionDeclMap( + bool keep_result_in_memory, + Materializer::PersistentVariableDelegate *result_delegate, + ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangExpressionDeclMap() override; + + //------------------------------------------------------------------ + /// Enable the state needed for parsing and IR transformation. + /// + /// @param[in] exe_ctx + /// The execution context to use when finding types for variables. + /// Also used to find a "scratch" AST context to store result types. + /// + /// @param[in] materializer + /// If non-NULL, the materializer to populate with information about + /// the variables to use + /// + /// @return + /// True if parsing is possible; false if it is unsafe to continue. + //------------------------------------------------------------------ + bool WillParse(ExecutionContext &exe_ctx, Materializer *materializer); + + void InstallCodeGenerator(clang::ASTConsumer *code_gen); + + //------------------------------------------------------------------ + /// [Used by ClangExpressionParser] For each variable that had an unknown + /// type at the beginning of parsing, determine its final type now. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool ResolveUnknownTypes(); + + //------------------------------------------------------------------ + /// Disable the state needed for parsing and IR transformation. + //------------------------------------------------------------------ + void DidParse(); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the list of persistent + /// variables for the process. + /// + /// @param[in] decl + /// The Clang declaration for the persistent variable, used for + /// lookup during parsing. + /// + /// @param[in] name + /// The name of the persistent variable, usually $something. + /// + /// @param[in] type + /// The type of the variable, in the Clang parser's context. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool AddPersistentVariable(const clang::NamedDecl *decl, + const ConstString &name, TypeFromParser type, + bool is_result, bool is_lvalue); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the struct that needs to + /// be materialized each time the expression runs. + /// + /// @param[in] decl + /// The Clang declaration for the variable. + /// + /// @param[in] name + /// The name of the variable. + /// + /// @param[in] value + /// The LLVM IR value for this variable. + /// + /// @param[in] size + /// The size of the variable in bytes. + /// + /// @param[in] alignment + /// The required alignment of the variable in bytes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool AddValueToStruct(const clang::NamedDecl *decl, const ConstString &name, + llvm::Value *value, size_t size, + lldb::offset_t alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Finalize the struct, laying out the position + /// of each object in it. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool DoStructLayout(); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get general information about the laid-out + /// struct after DoStructLayout() has been called. + /// + /// @param[out] num_elements + /// The number of elements in the struct. + /// + /// @param[out] size + /// The size of the struct, in bytes. + /// + /// @param[out] alignment + /// The alignment of the struct, in bytes. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool GetStructInfo(uint32_t &num_elements, size_t &size, + lldb::offset_t &alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get specific information about one field + /// of the laid-out struct after DoStructLayout() has been called. + /// + /// @param[out] decl + /// The parsed Decl for the field, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. In the case of the result + /// value, this will have the name $__lldb_result even if the + /// result value ends up having the name $1. This is an + /// implementation detail of IRForTarget. + /// + /// @param[out] value + /// The IR value for the field (usually a GlobalVariable). In + /// the case of the result value, this will have the correct + /// name ($1, for instance). This is an implementation detail + /// of IRForTarget. + /// + /// @param[out] offset + /// The offset of the field from the beginning of the struct. + /// As long as the struct is aligned according to its required + /// alignment, this offset will align the field correctly. + /// + /// @param[out] name + /// The name of the field as used in materialization. + /// + /// @param[in] index + /// The index of the field about which information is requested. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool GetStructElement(const clang::NamedDecl *&decl, llvm::Value *&value, + lldb::offset_t &offset, ConstString &name, + uint32_t index); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get information about a function given its + /// Decl. + /// + /// @param[in] decl + /// The parsed Decl for the Function, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. + /// + /// @param[out] ptr + /// The absolute address of the function in the target. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool GetFunctionInfo(const clang::NamedDecl *decl, uint64_t &ptr); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get the address of a symbol given nothing + /// but its name. + /// + /// @param[in] target + /// The target to find the symbol in. If not provided, + /// then the current parsing context's Target. + /// + /// @param[in] process + /// The process to use. For Objective-C symbols, the process's + /// Objective-C language runtime may be queried if the process + /// is non-NULL. + /// + /// @param[in] name + /// The name of the symbol. + /// + /// @param[in] module + /// The module to limit the search to. This can be NULL + /// + /// @return + /// Valid load address for the symbol + //------------------------------------------------------------------ + lldb::addr_t GetSymbolAddress(Target &target, Process *process, + const ConstString &name, + lldb::SymbolType symbol_type, + Module *module = NULL); + + lldb::addr_t GetSymbolAddress(const ConstString &name, + lldb::SymbolType symbol_type); + + //------------------------------------------------------------------ + /// [Used by IRInterpreter] Get basic target information. + /// + /// @param[out] byte_order + /// The byte order of the target. + /// + /// @param[out] address_byte_size + /// The size of a pointer in bytes. + /// + /// @return + /// True if the information could be determined; false + /// otherwise. + //------------------------------------------------------------------ + struct TargetInfo { + lldb::ByteOrder byte_order; + size_t address_byte_size; + + TargetInfo() : byte_order(lldb::eByteOrderInvalid), address_byte_size(0) {} + + bool IsValid() { + return (byte_order != lldb::eByteOrderInvalid && address_byte_size != 0); } - - //---------------------------------------------------------------------- - /// Get this parser's ID for use in extracting parser- and JIT-specific - /// data from persistent variables. - //---------------------------------------------------------------------- - uint64_t - GetParserID() - { - return (uint64_t)this; + }; + TargetInfo GetTargetInfo(); + + //------------------------------------------------------------------ + /// [Used by ClangASTSource] Find all entities matching a given name, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void FindExternalVisibleDecls(NameSearchContext &context) override; + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module/namespace, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// @param[in] name + /// The name as a plain C string. The NameSearchContext contains + /// a DeclarationName for the name so at first the name may seem + /// redundant, but ClangExpressionDeclMap operates in RTTI land so + /// it can't access DeclarationName. + /// + /// @param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void FindExternalVisibleDecls(NameSearchContext &context, + lldb::ModuleSP module, + CompilerDeclContext &namespace_decl, + unsigned int current_id); + +private: + ExpressionVariableList + m_found_entities; ///< All entities that were looked up for the parser. + ExpressionVariableList + m_struct_members; ///< All entities that need to be placed in the struct. + bool m_keep_result_in_memory; ///< True if result persistent variables + ///generated by this expression should stay in + ///memory. + Materializer::PersistentVariableDelegate + *m_result_delegate; ///< If non-NULL, used to report expression results to + ///ClangUserExpression. + + //---------------------------------------------------------------------- + /// The following values should not live beyond parsing + //---------------------------------------------------------------------- + class ParserVars { + public: + ParserVars(ClangExpressionDeclMap &decl_map) : m_decl_map(decl_map) {} + + Target *GetTarget() { + if (m_exe_ctx.GetTargetPtr()) + return m_exe_ctx.GetTargetPtr(); + else if (m_sym_ctx.target_sp) + m_sym_ctx.target_sp.get(); + return NULL; } - - //------------------------------------------------------------------ - /// Given a target, find a data symbol that has the given name. - /// - /// @param[in] target - /// The target to use as the basis for the search. - /// - /// @param[in] name - /// The name as a plain C string. - /// - /// @param[in] module - /// The module to limit the search to. This can be NULL - /// - /// @return - /// The LLDB Symbol found, or NULL if none was found. - //------------------------------------------------------------------ - const Symbol * - FindGlobalDataSymbol (Target &target, - const ConstString &name, - Module *module = NULL); - - //------------------------------------------------------------------ - /// Given a target, find a variable that matches the given name and - /// type. - /// - /// @param[in] target - /// The target to use as a basis for finding the variable. - /// - /// @param[in] module - /// If non-NULL, the module to search. - /// - /// @param[in] name - /// The name as a plain C string. - /// - /// @param[in] namespace_decl - /// If non-NULL and module is non-NULL, the parent namespace. - /// - /// @param[in] type - /// The required type for the variable. This function may be called - /// during parsing, in which case we don't know its type; hence the - /// default. - /// - /// @return - /// The LLDB Variable found, or NULL if none was found. - //------------------------------------------------------------------ - lldb::VariableSP - FindGlobalVariable (Target &target, - lldb::ModuleSP &module, - const ConstString &name, - CompilerDeclContext *namespace_decl, - TypeFromUser *type = NULL); - - //------------------------------------------------------------------ - /// Get the value of a variable in a given execution context and return - /// the associated Types if needed. - /// - /// @param[in] var - /// The variable to evaluate. - /// - /// @param[out] var_location - /// The variable location value to fill in - /// - /// @param[out] found_type - /// The type of the found value, as it was found in the user process. - /// This is only useful when the variable is being inspected on behalf - /// of the parser, hence the default. - /// - /// @param[out] parser_type - /// The type of the found value, as it was copied into the parser's - /// AST context. This is only useful when the variable is being - /// inspected on behalf of the parser, hence the default. - /// - /// @param[in] decl - /// The Decl to be looked up. - /// - /// @return - /// Return true if the value was successfully filled in. - //------------------------------------------------------------------ - bool - GetVariableValue (lldb::VariableSP &var, - lldb_private::Value &var_location, - TypeFromUser *found_type = NULL, - TypeFromParser *parser_type = NULL); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given LLDB - /// Variable, and put it in the Tuple list. - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] var - /// The LLDB Variable that needs a Decl. - /// - /// @param[in] valobj - /// The LLDB ValueObject for that variable. - //------------------------------------------------------------------ - void - AddOneVariable (NameSearchContext &context, - lldb::VariableSP var, - lldb::ValueObjectSP valobj, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// persistent variable, and put it in the list of found entities. - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] pvar - /// The persistent variable that needs a Decl. - /// - /// @param[in] current_id - /// The ID of the current invocation of FindExternalVisibleDecls - /// for logging purposes. - //------------------------------------------------------------------ - void - AddOneVariable (NameSearchContext &context, - lldb::ExpressionVariableSP &pvar_sp, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given LLDB - /// symbol (treated as a variable), and put it in the list of found - /// entities. - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] var - /// The LLDB Variable that needs a Decl. - //------------------------------------------------------------------ - void - AddOneGenericVariable (NameSearchContext &context, - const Symbol &symbol, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// function. (Functions are not placed in the Tuple list.) Can - /// handle both fully typed functions and generic functions. - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] fun - /// The Function that needs to be created. If non-NULL, this is - /// a fully-typed function. - /// - /// @param[in] sym - /// The Symbol that corresponds to a function that needs to be - /// created with generic type (unitptr_t foo(...)). - //------------------------------------------------------------------ - void - AddOneFunction (NameSearchContext &context, - Function *fun, - Symbol *sym, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// register. - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] reg_info - /// The information corresponding to that register. - //------------------------------------------------------------------ - void - AddOneRegister (NameSearchContext &context, - const RegisterInfo *reg_info, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// type. (Types are not placed in the Tuple list.) - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] type - /// The type that needs to be created. - //------------------------------------------------------------------ - void - AddOneType (NameSearchContext &context, - TypeFromUser &type, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Generate a Decl for "*this" and add a member function declaration - /// to it for the expression, then report it. - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] type - /// The type for *this. - //------------------------------------------------------------------ - void - AddThisType(NameSearchContext &context, - TypeFromUser &type, - unsigned int current_id); - - ClangASTContext * - GetClangASTContext(); + + ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. + SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables + ///and types. + ClangPersistentVariables *m_persistent_vars = + nullptr; ///< The persistent variables for the process. + bool m_enable_lookups = false; ///< Set to true during parsing if we have + ///found the first "$__lldb" name. + TargetInfo m_target_info; ///< Basic information about the target. + Materializer *m_materializer = nullptr; ///< If non-NULL, the materializer + ///to use when reporting used + ///variables. + clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator + ///that receives new top-level + ///functions. + private: + ClangExpressionDeclMap &m_decl_map; + DISALLOW_COPY_AND_ASSIGN(ParserVars); + }; + + std::unique_ptr<ParserVars> m_parser_vars; + + //---------------------------------------------------------------------- + /// Activate parser-specific variables + //---------------------------------------------------------------------- + void EnableParserVars() { + if (!m_parser_vars.get()) + m_parser_vars.reset(new ParserVars(*this)); + } + + //---------------------------------------------------------------------- + /// Deallocate parser-specific variables + //---------------------------------------------------------------------- + void DisableParserVars() { m_parser_vars.reset(); } + + //---------------------------------------------------------------------- + /// The following values contain layout information for the materialized + /// struct, but are not specific to a single materialization + //---------------------------------------------------------------------- + struct StructVars { + StructVars() + : m_struct_alignment(0), m_struct_size(0), m_struct_laid_out(false), + m_result_name(), m_object_pointer_type(NULL, NULL) {} + + lldb::offset_t + m_struct_alignment; ///< The alignment of the struct in bytes. + size_t m_struct_size; ///< The size of the struct in bytes. + bool m_struct_laid_out; ///< True if the struct has been laid out and the + ///layout is valid (that is, no new fields have been + ///added since). + ConstString + m_result_name; ///< The name of the result variable ($1, for example) + TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if + ///one exists + }; + + std::unique_ptr<StructVars> m_struct_vars; + + //---------------------------------------------------------------------- + /// Activate struct variables + //---------------------------------------------------------------------- + void EnableStructVars() { + if (!m_struct_vars.get()) + m_struct_vars.reset(new struct StructVars); + } + + //---------------------------------------------------------------------- + /// Deallocate struct variables + //---------------------------------------------------------------------- + void DisableStructVars() { m_struct_vars.reset(); } + + //---------------------------------------------------------------------- + /// Get this parser's ID for use in extracting parser- and JIT-specific + /// data from persistent variables. + //---------------------------------------------------------------------- + uint64_t GetParserID() { return (uint64_t) this; } + + //------------------------------------------------------------------ + /// Given a target, find a data symbol that has the given name. + /// + /// @param[in] target + /// The target to use as the basis for the search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @param[in] module + /// The module to limit the search to. This can be NULL + /// + /// @return + /// The LLDB Symbol found, or NULL if none was found. + //------------------------------------------------------------------ + const Symbol *FindGlobalDataSymbol(Target &target, const ConstString &name, + Module *module = NULL); + + //------------------------------------------------------------------ + /// Given a target, find a variable that matches the given name and + /// type. + /// + /// @param[in] target + /// The target to use as a basis for finding the variable. + /// + /// @param[in] module + /// If non-NULL, the module to search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @param[in] namespace_decl + /// If non-NULL and module is non-NULL, the parent namespace. + /// + /// @param[in] type + /// The required type for the variable. This function may be called + /// during parsing, in which case we don't know its type; hence the + /// default. + /// + /// @return + /// The LLDB Variable found, or NULL if none was found. + //------------------------------------------------------------------ + lldb::VariableSP FindGlobalVariable(Target &target, lldb::ModuleSP &module, + const ConstString &name, + CompilerDeclContext *namespace_decl, + TypeFromUser *type = NULL); + + //------------------------------------------------------------------ + /// Get the value of a variable in a given execution context and return + /// the associated Types if needed. + /// + /// @param[in] var + /// The variable to evaluate. + /// + /// @param[out] var_location + /// The variable location value to fill in + /// + /// @param[out] found_type + /// The type of the found value, as it was found in the user process. + /// This is only useful when the variable is being inspected on behalf + /// of the parser, hence the default. + /// + /// @param[out] parser_type + /// The type of the found value, as it was copied into the parser's + /// AST context. This is only useful when the variable is being + /// inspected on behalf of the parser, hence the default. + /// + /// @param[in] decl + /// The Decl to be looked up. + /// + /// @return + /// Return true if the value was successfully filled in. + //------------------------------------------------------------------ + bool GetVariableValue(lldb::VariableSP &var, + lldb_private::Value &var_location, + TypeFromUser *found_type = NULL, + TypeFromParser *parser_type = NULL); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// Variable, and put it in the Tuple list. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + /// + /// @param[in] valobj + /// The LLDB ValueObject for that variable. + //------------------------------------------------------------------ + void AddOneVariable(NameSearchContext &context, lldb::VariableSP var, + lldb::ValueObjectSP valobj, unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// persistent variable, and put it in the list of found entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] pvar + /// The persistent variable that needs a Decl. + /// + /// @param[in] current_id + /// The ID of the current invocation of FindExternalVisibleDecls + /// for logging purposes. + //------------------------------------------------------------------ + void AddOneVariable(NameSearchContext &context, + lldb::ExpressionVariableSP &pvar_sp, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// symbol (treated as a variable), and put it in the list of found + /// entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + //------------------------------------------------------------------ + void AddOneGenericVariable(NameSearchContext &context, const Symbol &symbol, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// function. (Functions are not placed in the Tuple list.) Can + /// handle both fully typed functions and generic functions. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] fun + /// The Function that needs to be created. If non-NULL, this is + /// a fully-typed function. + /// + /// @param[in] sym + /// The Symbol that corresponds to a function that needs to be + /// created with generic type (unitptr_t foo(...)). + //------------------------------------------------------------------ + void AddOneFunction(NameSearchContext &context, Function *fun, Symbol *sym, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// register. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] reg_info + /// The information corresponding to that register. + //------------------------------------------------------------------ + void AddOneRegister(NameSearchContext &context, const RegisterInfo *reg_info, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// type. (Types are not placed in the Tuple list.) + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] type + /// The type that needs to be created. + //------------------------------------------------------------------ + void AddOneType(NameSearchContext &context, TypeFromUser &type, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Generate a Decl for "*this" and add a member function declaration + /// to it for the expression, then report it. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] type + /// The type for *this. + //------------------------------------------------------------------ + void AddThisType(NameSearchContext &context, TypeFromUser &type, + unsigned int current_id); + + ClangASTContext *GetClangASTContext(); }; - + } // namespace lldb_private #endif // liblldb_ClangExpressionDeclMap_h_ diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h index bcd30ec4af2..4562bf9a67b 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h @@ -12,17 +12,17 @@ // C Includes // C++ Includes -#include <string> #include <map> +#include <string> #include <vector> // Other libraries and framework includes // Project includes -#include "lldb/lldb-forward.h" -#include "lldb/lldb-private.h" #include "lldb/Core/ClangForward.h" #include "lldb/Expression/ExpressionTypeSystemHelper.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" namespace lldb_private { @@ -31,52 +31,43 @@ class RecordingMemoryManager; //---------------------------------------------------------------------- // ClangExpressionHelper //---------------------------------------------------------------------- -class ClangExpressionHelper : public ExpressionTypeSystemHelper -{ +class ClangExpressionHelper : public ExpressionTypeSystemHelper { public: - static bool classof(const ExpressionTypeSystemHelper *ts) - { - return ts->getKind() == eKindClangHelper; - } + static bool classof(const ExpressionTypeSystemHelper *ts) { + return ts->getKind() == eKindClangHelper; + } + + ClangExpressionHelper() + : ExpressionTypeSystemHelper( + ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper) {} + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual ~ClangExpressionHelper() {} - ClangExpressionHelper () : - ExpressionTypeSystemHelper(ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper) - { - } + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + virtual ClangExpressionDeclMap *DeclMap() = 0; - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - virtual ~ClangExpressionHelper () - { - } - - //------------------------------------------------------------------ - /// Return the object that the parser should use when resolving external - /// values. May be NULL if everything should be self-contained. - //------------------------------------------------------------------ - virtual ClangExpressionDeclMap * - DeclMap () = 0; - - //------------------------------------------------------------------ - /// Return the object that the parser should allow to access ASTs. - /// May be NULL if the ASTs do not need to be transformed. - /// - /// @param[in] passthrough - /// The ASTConsumer that the returned transformer should send - /// the ASTs to after transformation. - //------------------------------------------------------------------ - virtual clang::ASTConsumer * - ASTTransformer(clang::ASTConsumer *passthrough) = 0; + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + virtual clang::ASTConsumer * + ASTTransformer(clang::ASTConsumer *passthrough) = 0; - virtual void - CommitPersistentDecls() - { - } + virtual void CommitPersistentDecls() {} protected: }; } // namespace lldb_private -#endif // liblldb_ClangExpression_h_ +#endif // liblldb_ClangExpression_h_ diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 6a27cd3ef3f..95efb5c76c8 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -17,12 +17,12 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Version.h" +#include "clang/Basic/Version.h" #include "clang/CodeGen/CodeGenAction.h" #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Edit/Commit.h" -#include "clang/Edit/EditsReceiver.h" #include "clang/Edit/EditedSource.h" +#include "clang/Edit/EditsReceiver.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" @@ -32,8 +32,8 @@ #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/ParseAST.h" -#include "clang/Rewrite/Frontend/FrontendActions.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Rewrite/Frontend/FrontendActions.h" #include "clang/Sema/SemaConsumer.h" #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" @@ -50,19 +50,19 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" // Project includes -#include "ClangExpressionParser.h" #include "ClangDiagnostic.h" +#include "ClangExpressionParser.h" #include "ClangASTSource.h" -#include "ClangExpressionHelper.h" #include "ClangExpressionDeclMap.h" +#include "ClangExpressionHelper.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" #include "IRForTarget.h" @@ -100,931 +100,888 @@ using namespace lldb_private; // Utility Methods for Clang //===----------------------------------------------------------------------===// - -class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks -{ - ClangModulesDeclVendor &m_decl_vendor; - ClangPersistentVariables &m_persistent_vars; - StreamString m_error_stream; - bool m_has_errors = false; +class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks { + ClangModulesDeclVendor &m_decl_vendor; + ClangPersistentVariables &m_persistent_vars; + StreamString m_error_stream; + bool m_has_errors = false; public: - LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor, - ClangPersistentVariables &persistent_vars) : - m_decl_vendor(decl_vendor), - m_persistent_vars(persistent_vars) - { - } - - void - moduleImport(SourceLocation import_location, - clang::ModuleIdPath path, - const clang::Module * /*null*/) override - { - std::vector<ConstString> string_path; - - for (const std::pair<IdentifierInfo *, SourceLocation> &component : path) - { - string_path.push_back(ConstString(component.first->getName())); - } - - StreamString error_stream; - - ClangModulesDeclVendor::ModuleVector exported_modules; - - if (!m_decl_vendor.AddModule(string_path, &exported_modules, m_error_stream)) - { - m_has_errors = true; - } - - for (ClangModulesDeclVendor::ModuleID module : exported_modules) - { - m_persistent_vars.AddHandLoadedClangModule(module); - } - } - - bool hasErrors() - { - return m_has_errors; - } - - const std::string &getErrorString() - { - return m_error_stream.GetString(); - } -}; + LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor, + ClangPersistentVariables &persistent_vars) + : m_decl_vendor(decl_vendor), m_persistent_vars(persistent_vars) {} -class ClangDiagnosticManagerAdapter : public clang::DiagnosticConsumer -{ -public: - ClangDiagnosticManagerAdapter() : m_passthrough(new clang::TextDiagnosticBuffer) {} + void moduleImport(SourceLocation import_location, clang::ModuleIdPath path, + const clang::Module * /*null*/) override { + std::vector<ConstString> string_path; - ClangDiagnosticManagerAdapter(const std::shared_ptr<clang::TextDiagnosticBuffer> &passthrough) - : m_passthrough(passthrough) - { + for (const std::pair<IdentifierInfo *, SourceLocation> &component : path) { + string_path.push_back(ConstString(component.first->getName())); } - void - ResetManager(DiagnosticManager *manager = nullptr) - { - m_manager = manager; - } + StreamString error_stream; - void - HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) - { - if (m_manager) - { - llvm::SmallVector<char, 32> diag_str; - Info.FormatDiagnostic(diag_str); - diag_str.push_back('\0'); - const char *data = diag_str.data(); - - lldb_private::DiagnosticSeverity severity; - bool make_new_diagnostic = true; - - switch (DiagLevel) - { - case DiagnosticsEngine::Level::Fatal: - case DiagnosticsEngine::Level::Error: - severity = eDiagnosticSeverityError; - break; - case DiagnosticsEngine::Level::Warning: - severity = eDiagnosticSeverityWarning; - break; - case DiagnosticsEngine::Level::Remark: - case DiagnosticsEngine::Level::Ignored: - severity = eDiagnosticSeverityRemark; - break; - case DiagnosticsEngine::Level::Note: - m_manager->AppendMessageToDiagnostic(data); - make_new_diagnostic = false; - } - if (make_new_diagnostic) - { - ClangDiagnostic *new_diagnostic = new ClangDiagnostic(data, severity, Info.getID()); - m_manager->AddDiagnostic(new_diagnostic); - - // Don't store away warning fixits, since the compiler doesn't have enough - // context in an expression for the warning to be useful. - // FIXME: Should we try to filter out FixIts that apply to our generated - // code, and not the user's expression? - if (severity == eDiagnosticSeverityError) - { - size_t num_fixit_hints = Info.getNumFixItHints(); - for (size_t i = 0; i < num_fixit_hints; i++) - { - const clang::FixItHint &fixit = Info.getFixItHint(i); - if (!fixit.isNull()) - new_diagnostic->AddFixitHint(fixit); - } - } - } - } - - m_passthrough->HandleDiagnostic(DiagLevel, Info); - } + ClangModulesDeclVendor::ModuleVector exported_modules; - void - FlushDiagnostics(DiagnosticsEngine &Diags) - { - m_passthrough->FlushDiagnostics(Diags); + if (!m_decl_vendor.AddModule(string_path, &exported_modules, + m_error_stream)) { + m_has_errors = true; } - DiagnosticConsumer * - clone(DiagnosticsEngine &Diags) const - { - return new ClangDiagnosticManagerAdapter(m_passthrough); + for (ClangModulesDeclVendor::ModuleID module : exported_modules) { + m_persistent_vars.AddHandLoadedClangModule(module); } + } - clang::TextDiagnosticBuffer * - GetPassthrough() - { - return m_passthrough.get(); - } + bool hasErrors() { return m_has_errors; } -private: - DiagnosticManager *m_manager = nullptr; - std::shared_ptr<clang::TextDiagnosticBuffer> m_passthrough; + const std::string &getErrorString() { return m_error_stream.GetString(); } }; -//===----------------------------------------------------------------------===// -// Implementation of ClangExpressionParser -//===----------------------------------------------------------------------===// - -ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, - Expression &expr, - bool generate_debug_info) : - ExpressionParser (exe_scope, expr, generate_debug_info), - m_compiler (), - m_code_generator (), - m_pp_callbacks(nullptr) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - // We can't compile expressions without a target. So if the exe_scope is null or doesn't have a target, - // then we just need to get out of here. I'll lldb_assert and not make any of the compiler objects since - // I can't return errors directly from the constructor. Further calls will check if the compiler was made and - // bag out if it wasn't. - - if (!exe_scope) - { - lldb_assert(exe_scope, "Can't make an expression parser with a null scope.", __FUNCTION__, __FILE__, __LINE__); - return; - } - - lldb::TargetSP target_sp; - target_sp = exe_scope->CalculateTarget(); - if (!target_sp) - { - lldb_assert(target_sp.get(), "Can't make an expression parser with a null target.", __FUNCTION__, __FILE__, __LINE__); - return; - } - - // 1. Create a new compiler instance. - m_compiler.reset(new CompilerInstance()); - lldb::LanguageType frame_lang = expr.Language(); // defaults to lldb::eLanguageTypeUnknown - bool overridden_target_opts = false; - lldb_private::LanguageRuntime *lang_rt = nullptr; - - std::string abi; - ArchSpec target_arch; - target_arch = target_sp->GetArchitecture(); - - const auto target_machine = target_arch.GetMachine(); - - // If the expression is being evaluated in the context of an existing - // stack frame, we introspect to see if the language runtime is available. - - lldb::StackFrameSP frame_sp = exe_scope->CalculateStackFrame(); - lldb::ProcessSP process_sp = exe_scope->CalculateProcess(); - - // Make sure the user hasn't provided a preferred execution language - // with `expression --language X -- ...` - if (frame_sp && frame_lang == lldb::eLanguageTypeUnknown) - frame_lang = frame_sp->GetLanguage(); - - if (process_sp && frame_lang != lldb::eLanguageTypeUnknown) - { - lang_rt = process_sp->GetLanguageRuntime(frame_lang); - if (log) - log->Printf("Frame has language of type %s", Language::GetNameForLanguageType(frame_lang)); - } - - // 2. Configure the compiler with a set of default options that are appropriate - // for most situations. - if (target_arch.IsValid()) - { - std::string triple = target_arch.GetTriple().str(); - m_compiler->getTargetOpts().Triple = triple; - if (log) - log->Printf("Using %s as the target triple", m_compiler->getTargetOpts().Triple.c_str()); - } - else - { - // If we get here we don't have a valid target and just have to guess. - // Sometimes this will be ok to just use the host target triple (when we evaluate say "2+3", but other - // expressions like breakpoint conditions and other things that _are_ target specific really shouldn't just be - // using the host triple. In such a case the language runtime should expose an overridden options set (3), - // below. - m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); - if (log) - log->Printf("Using default target triple of %s", m_compiler->getTargetOpts().Triple.c_str()); - } - // Now add some special fixes for known architectures: - // Any arm32 iOS environment, but not on arm64 - if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos && - m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos && - m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) - { - m_compiler->getTargetOpts().ABI = "apcs-gnu"; - } - // Supported subsets of x86 - if (target_machine == llvm::Triple::x86 || - target_machine == llvm::Triple::x86_64) - { - m_compiler->getTargetOpts().Features.push_back("+sse"); - m_compiler->getTargetOpts().Features.push_back("+sse2"); - } - - // Set the target CPU to generate code for. - // This will be empty for any CPU that doesn't really need to make a special CPU string. - m_compiler->getTargetOpts().CPU = target_arch.GetClangTargetCPU(); - - // Set the target ABI - abi = GetClangTargetABI(target_arch); - if (!abi.empty()) - m_compiler->getTargetOpts().ABI = abi; - - // 3. Now allow the runtime to provide custom configuration options for the target. - // In this case, a specialized language runtime is available and we can query it for extra options. - // For 99% of use cases, this will not be needed and should be provided when basic platform detection is not enough. - if (lang_rt) - overridden_target_opts = lang_rt->GetOverrideExprOptions(m_compiler->getTargetOpts()); - - if (overridden_target_opts) - if (log) - { - log->Debug("Using overridden target options for the expression evaluation"); - - auto opts = m_compiler->getTargetOpts(); - log->Debug("Triple: '%s'", opts.Triple.c_str()); - log->Debug("CPU: '%s'", opts.CPU.c_str()); - log->Debug("FPMath: '%s'", opts.FPMath.c_str()); - log->Debug("ABI: '%s'", opts.ABI.c_str()); - log->Debug("LinkerVersion: '%s'", opts.LinkerVersion.c_str()); - StringList::LogDump(log, opts.FeaturesAsWritten, "FeaturesAsWritten"); - StringList::LogDump(log, opts.Features, "Features"); - StringList::LogDump(log, opts.Reciprocals, "Reciprocals"); - } - - // 4. Create and install the target on the compiler. - m_compiler->createDiagnostics(); - auto target_info = TargetInfo::CreateTargetInfo(m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts); - if (log) - { - log->Printf("Using SIMD alignment: %d", target_info->getSimdDefaultAlign()); - log->Printf("Target datalayout string: '%s'", target_info->getDataLayout().getStringRepresentation().c_str()); - log->Printf("Target ABI: '%s'", target_info->getABI().str().c_str()); - log->Printf("Target vector alignment: %d", target_info->getMaxVectorAlign()); - } - m_compiler->setTarget(target_info); - - assert (m_compiler->hasTarget()); - - // 5. Set language options. - lldb::LanguageType language = expr.Language(); - - switch (language) - { - case lldb::eLanguageTypeC: - case lldb::eLanguageTypeC89: - case lldb::eLanguageTypeC99: - case lldb::eLanguageTypeC11: - // FIXME: the following language option is a temporary workaround, - // to "ask for C, get C++." - // For now, the expression parser must use C++ anytime the - // language is a C family language, because the expression parser - // uses features of C++ to capture values. - m_compiler->getLangOpts().CPlusPlus = true; +class ClangDiagnosticManagerAdapter : public clang::DiagnosticConsumer { +public: + ClangDiagnosticManagerAdapter() + : m_passthrough(new clang::TextDiagnosticBuffer) {} + + ClangDiagnosticManagerAdapter( + const std::shared_ptr<clang::TextDiagnosticBuffer> &passthrough) + : m_passthrough(passthrough) {} + + void ResetManager(DiagnosticManager *manager = nullptr) { + m_manager = manager; + } + + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const clang::Diagnostic &Info) { + if (m_manager) { + llvm::SmallVector<char, 32> diag_str; + Info.FormatDiagnostic(diag_str); + diag_str.push_back('\0'); + const char *data = diag_str.data(); + + lldb_private::DiagnosticSeverity severity; + bool make_new_diagnostic = true; + + switch (DiagLevel) { + case DiagnosticsEngine::Level::Fatal: + case DiagnosticsEngine::Level::Error: + severity = eDiagnosticSeverityError; break; - case lldb::eLanguageTypeObjC: - m_compiler->getLangOpts().ObjC1 = true; - m_compiler->getLangOpts().ObjC2 = true; - // FIXME: the following language option is a temporary workaround, - // to "ask for ObjC, get ObjC++" (see comment above). - m_compiler->getLangOpts().CPlusPlus = true; + case DiagnosticsEngine::Level::Warning: + severity = eDiagnosticSeverityWarning; break; - case lldb::eLanguageTypeC_plus_plus: - case lldb::eLanguageTypeC_plus_plus_11: - case lldb::eLanguageTypeC_plus_plus_14: - m_compiler->getLangOpts().CPlusPlus11 = true; - m_compiler->getHeaderSearchOpts().UseLibcxx = true; - LLVM_FALLTHROUGH; - case lldb::eLanguageTypeC_plus_plus_03: - m_compiler->getLangOpts().CPlusPlus = true; - // FIXME: the following language option is a temporary workaround, - // to "ask for C++, get ObjC++". Apple hopes to remove this requirement - // on non-Apple platforms, but for now it is needed. - m_compiler->getLangOpts().ObjC1 = true; - break; - case lldb::eLanguageTypeObjC_plus_plus: - case lldb::eLanguageTypeUnknown: - default: - m_compiler->getLangOpts().ObjC1 = true; - m_compiler->getLangOpts().ObjC2 = true; - m_compiler->getLangOpts().CPlusPlus = true; - m_compiler->getLangOpts().CPlusPlus11 = true; - m_compiler->getHeaderSearchOpts().UseLibcxx = true; + case DiagnosticsEngine::Level::Remark: + case DiagnosticsEngine::Level::Ignored: + severity = eDiagnosticSeverityRemark; break; + case DiagnosticsEngine::Level::Note: + m_manager->AppendMessageToDiagnostic(data); + make_new_diagnostic = false; + } + if (make_new_diagnostic) { + ClangDiagnostic *new_diagnostic = + new ClangDiagnostic(data, severity, Info.getID()); + m_manager->AddDiagnostic(new_diagnostic); + + // Don't store away warning fixits, since the compiler doesn't have + // enough + // context in an expression for the warning to be useful. + // FIXME: Should we try to filter out FixIts that apply to our generated + // code, and not the user's expression? + if (severity == eDiagnosticSeverityError) { + size_t num_fixit_hints = Info.getNumFixItHints(); + for (size_t i = 0; i < num_fixit_hints; i++) { + const clang::FixItHint &fixit = Info.getFixItHint(i); + if (!fixit.isNull()) + new_diagnostic->AddFixitHint(fixit); + } + } + } } - m_compiler->getLangOpts().Bool = true; - m_compiler->getLangOpts().WChar = true; - m_compiler->getLangOpts().Blocks = true; - m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients - if (expr.DesiredResultType() == Expression::eResultTypeId) - m_compiler->getLangOpts().DebuggerCastResultToId = true; - - m_compiler->getLangOpts().CharIsSigned = - ArchSpec(m_compiler->getTargetOpts().Triple.c_str()).CharIsSignedByDefault(); - - // Spell checking is a nice feature, but it ends up completing a - // lot of types that we didn't strictly speaking need to complete. - // As a result, we spend a long time parsing and importing debug - // information. - m_compiler->getLangOpts().SpellChecking = false; - - if (process_sp && m_compiler->getLangOpts().ObjC1) - { - if (process_sp->GetObjCLanguageRuntime()) - { - if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2) - m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7)); - else - m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7)); + m_passthrough->HandleDiagnostic(DiagLevel, Info); + } - if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing()) - m_compiler->getLangOpts().DebuggerObjCLiteral = true; - } - } + void FlushDiagnostics(DiagnosticsEngine &Diags) { + m_passthrough->FlushDiagnostics(Diags); + } - m_compiler->getLangOpts().ThreadsafeStatics = false; - m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access - m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name - - // Set CodeGen options - m_compiler->getCodeGenOpts().EmitDeclMetadata = true; - m_compiler->getCodeGenOpts().InstrumentFunctions = false; - m_compiler->getCodeGenOpts().DisableFPElim = true; - m_compiler->getCodeGenOpts().OmitLeafFramePointer = false; - if (generate_debug_info) - m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo); - else - m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo); - - // Disable some warnings. - m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, - "unused-value", clang::diag::Severity::Ignored, SourceLocation()); - m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, - "odr", clang::diag::Severity::Ignored, SourceLocation()); - - // Inform the target of the language options - // - // FIXME: We shouldn't need to do this, the target should be immutable once - // created. This complexity should be lifted elsewhere. - m_compiler->getTarget().adjust(m_compiler->getLangOpts()); - - // 6. Set up the diagnostic buffer for reporting errors - - m_compiler->getDiagnostics().setClient(new ClangDiagnosticManagerAdapter); - - // 7. Set up the source management objects inside the compiler - - clang::FileSystemOptions file_system_options; - m_file_manager.reset(new clang::FileManager(file_system_options)); - - if (!m_compiler->hasSourceManager()) - m_compiler->createSourceManager(*m_file_manager.get()); - - m_compiler->createFileManager(); - m_compiler->createPreprocessor(TU_Complete); - - if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor()) - { - ClangPersistentVariables *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(target_sp->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); - std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars)); - m_pp_callbacks = static_cast<LLDBPreprocessorCallbacks*>(pp_callbacks.get()); - m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); - } - - // 8. Most of this we get from the CompilerInstance, but we - // also want to give the context an ExternalASTSource. - m_selector_table.reset(new SelectorTable()); - m_builtin_context.reset(new Builtin::Context()); - - std::unique_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(), - m_compiler->getSourceManager(), - m_compiler->getPreprocessor().getIdentifierTable(), - *m_selector_table.get(), - *m_builtin_context.get())); - - ast_context->InitBuiltinTypes(m_compiler->getTarget()); - - ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); - ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); - - if (decl_map) - { - llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy()); - decl_map->InstallASTContext(ast_context.get()); - ast_context->setExternalSource(ast_source); - } + DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { + return new ClangDiagnosticManagerAdapter(m_passthrough); + } - m_ast_context.reset(new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str())); - m_ast_context->setASTContext(ast_context.get()); - m_compiler->setASTContext(ast_context.release()); + clang::TextDiagnosticBuffer *GetPassthrough() { return m_passthrough.get(); } - std::string module_name("$__lldb_module"); +private: + DiagnosticManager *m_manager = nullptr; + std::shared_ptr<clang::TextDiagnosticBuffer> m_passthrough; +}; - m_llvm_context.reset(new LLVMContext()); - m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(), - module_name, - m_compiler->getHeaderSearchOpts(), - m_compiler->getPreprocessorOpts(), - m_compiler->getCodeGenOpts(), - *m_llvm_context)); -} +//===----------------------------------------------------------------------===// +// Implementation of ClangExpressionParser +//===----------------------------------------------------------------------===// -ClangExpressionParser::~ClangExpressionParser() -{ +ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, + Expression &expr, + bool generate_debug_info) + : ExpressionParser(exe_scope, expr, generate_debug_info), m_compiler(), + m_code_generator(), m_pp_callbacks(nullptr) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + // We can't compile expressions without a target. So if the exe_scope is null + // or doesn't have a target, + // then we just need to get out of here. I'll lldb_assert and not make any of + // the compiler objects since + // I can't return errors directly from the constructor. Further calls will + // check if the compiler was made and + // bag out if it wasn't. + + if (!exe_scope) { + lldb_assert(exe_scope, "Can't make an expression parser with a null scope.", + __FUNCTION__, __FILE__, __LINE__); + return; + } + + lldb::TargetSP target_sp; + target_sp = exe_scope->CalculateTarget(); + if (!target_sp) { + lldb_assert(target_sp.get(), + "Can't make an expression parser with a null target.", + __FUNCTION__, __FILE__, __LINE__); + return; + } + + // 1. Create a new compiler instance. + m_compiler.reset(new CompilerInstance()); + lldb::LanguageType frame_lang = + expr.Language(); // defaults to lldb::eLanguageTypeUnknown + bool overridden_target_opts = false; + lldb_private::LanguageRuntime *lang_rt = nullptr; + + std::string abi; + ArchSpec target_arch; + target_arch = target_sp->GetArchitecture(); + + const auto target_machine = target_arch.GetMachine(); + + // If the expression is being evaluated in the context of an existing + // stack frame, we introspect to see if the language runtime is available. + + lldb::StackFrameSP frame_sp = exe_scope->CalculateStackFrame(); + lldb::ProcessSP process_sp = exe_scope->CalculateProcess(); + + // Make sure the user hasn't provided a preferred execution language + // with `expression --language X -- ...` + if (frame_sp && frame_lang == lldb::eLanguageTypeUnknown) + frame_lang = frame_sp->GetLanguage(); + + if (process_sp && frame_lang != lldb::eLanguageTypeUnknown) { + lang_rt = process_sp->GetLanguageRuntime(frame_lang); + if (log) + log->Printf("Frame has language of type %s", + Language::GetNameForLanguageType(frame_lang)); + } + + // 2. Configure the compiler with a set of default options that are + // appropriate + // for most situations. + if (target_arch.IsValid()) { + std::string triple = target_arch.GetTriple().str(); + m_compiler->getTargetOpts().Triple = triple; + if (log) + log->Printf("Using %s as the target triple", + m_compiler->getTargetOpts().Triple.c_str()); + } else { + // If we get here we don't have a valid target and just have to guess. + // Sometimes this will be ok to just use the host target triple (when we + // evaluate say "2+3", but other + // expressions like breakpoint conditions and other things that _are_ target + // specific really shouldn't just be + // using the host triple. In such a case the language runtime should expose + // an overridden options set (3), + // below. + m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); + if (log) + log->Printf("Using default target triple of %s", + m_compiler->getTargetOpts().Triple.c_str()); + } + // Now add some special fixes for known architectures: + // Any arm32 iOS environment, but not on arm64 + if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos && + m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos && + m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) { + m_compiler->getTargetOpts().ABI = "apcs-gnu"; + } + // Supported subsets of x86 + if (target_machine == llvm::Triple::x86 || + target_machine == llvm::Triple::x86_64) { + m_compiler->getTargetOpts().Features.push_back("+sse"); + m_compiler->getTargetOpts().Features.push_back("+sse2"); + } + + // Set the target CPU to generate code for. + // This will be empty for any CPU that doesn't really need to make a special + // CPU string. + m_compiler->getTargetOpts().CPU = target_arch.GetClangTargetCPU(); + + // Set the target ABI + abi = GetClangTargetABI(target_arch); + if (!abi.empty()) + m_compiler->getTargetOpts().ABI = abi; + + // 3. Now allow the runtime to provide custom configuration options for the + // target. + // In this case, a specialized language runtime is available and we can query + // it for extra options. + // For 99% of use cases, this will not be needed and should be provided when + // basic platform detection is not enough. + if (lang_rt) + overridden_target_opts = + lang_rt->GetOverrideExprOptions(m_compiler->getTargetOpts()); + + if (overridden_target_opts) + if (log) { + log->Debug( + "Using overridden target options for the expression evaluation"); + + auto opts = m_compiler->getTargetOpts(); + log->Debug("Triple: '%s'", opts.Triple.c_str()); + log->Debug("CPU: '%s'", opts.CPU.c_str()); + log->Debug("FPMath: '%s'", opts.FPMath.c_str()); + log->Debug("ABI: '%s'", opts.ABI.c_str()); + log->Debug("LinkerVersion: '%s'", opts.LinkerVersion.c_str()); + StringList::LogDump(log, opts.FeaturesAsWritten, "FeaturesAsWritten"); + StringList::LogDump(log, opts.Features, "Features"); + StringList::LogDump(log, opts.Reciprocals, "Reciprocals"); + } + + // 4. Create and install the target on the compiler. + m_compiler->createDiagnostics(); + auto target_info = TargetInfo::CreateTargetInfo( + m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts); + if (log) { + log->Printf("Using SIMD alignment: %d", target_info->getSimdDefaultAlign()); + log->Printf("Target datalayout string: '%s'", + target_info->getDataLayout().getStringRepresentation().c_str()); + log->Printf("Target ABI: '%s'", target_info->getABI().str().c_str()); + log->Printf("Target vector alignment: %d", + target_info->getMaxVectorAlign()); + } + m_compiler->setTarget(target_info); + + assert(m_compiler->hasTarget()); + + // 5. Set language options. + lldb::LanguageType language = expr.Language(); + + switch (language) { + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC89: + case lldb::eLanguageTypeC99: + case lldb::eLanguageTypeC11: + // FIXME: the following language option is a temporary workaround, + // to "ask for C, get C++." + // For now, the expression parser must use C++ anytime the + // language is a C family language, because the expression parser + // uses features of C++ to capture values. + m_compiler->getLangOpts().CPlusPlus = true; + break; + case lldb::eLanguageTypeObjC: + m_compiler->getLangOpts().ObjC1 = true; + m_compiler->getLangOpts().ObjC2 = true; + // FIXME: the following language option is a temporary workaround, + // to "ask for ObjC, get ObjC++" (see comment above). + m_compiler->getLangOpts().CPlusPlus = true; + break; + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeC_plus_plus_11: + case lldb::eLanguageTypeC_plus_plus_14: + m_compiler->getLangOpts().CPlusPlus11 = true; + m_compiler->getHeaderSearchOpts().UseLibcxx = true; + LLVM_FALLTHROUGH; + case lldb::eLanguageTypeC_plus_plus_03: + m_compiler->getLangOpts().CPlusPlus = true; + // FIXME: the following language option is a temporary workaround, + // to "ask for C++, get ObjC++". Apple hopes to remove this requirement + // on non-Apple platforms, but for now it is needed. + m_compiler->getLangOpts().ObjC1 = true; + break; + case lldb::eLanguageTypeObjC_plus_plus: + case lldb::eLanguageTypeUnknown: + default: + m_compiler->getLangOpts().ObjC1 = true; + m_compiler->getLangOpts().ObjC2 = true; + m_compiler->getLangOpts().CPlusPlus = true; + m_compiler->getLangOpts().CPlusPlus11 = true; + m_compiler->getHeaderSearchOpts().UseLibcxx = true; + break; + } + + m_compiler->getLangOpts().Bool = true; + m_compiler->getLangOpts().WChar = true; + m_compiler->getLangOpts().Blocks = true; + m_compiler->getLangOpts().DebuggerSupport = + true; // Features specifically for debugger clients + if (expr.DesiredResultType() == Expression::eResultTypeId) + m_compiler->getLangOpts().DebuggerCastResultToId = true; + + m_compiler->getLangOpts().CharIsSigned = + ArchSpec(m_compiler->getTargetOpts().Triple.c_str()) + .CharIsSignedByDefault(); + + // Spell checking is a nice feature, but it ends up completing a + // lot of types that we didn't strictly speaking need to complete. + // As a result, we spend a long time parsing and importing debug + // information. + m_compiler->getLangOpts().SpellChecking = false; + + if (process_sp && m_compiler->getLangOpts().ObjC1) { + if (process_sp->GetObjCLanguageRuntime()) { + if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == + ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2) + m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, + VersionTuple(10, 7)); + else + m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, + VersionTuple(10, 7)); + + if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing()) + m_compiler->getLangOpts().DebuggerObjCLiteral = true; + } + } + + m_compiler->getLangOpts().ThreadsafeStatics = false; + m_compiler->getLangOpts().AccessControl = + false; // Debuggers get universal access + m_compiler->getLangOpts().DollarIdents = + true; // $ indicates a persistent variable name + + // Set CodeGen options + m_compiler->getCodeGenOpts().EmitDeclMetadata = true; + m_compiler->getCodeGenOpts().InstrumentFunctions = false; + m_compiler->getCodeGenOpts().DisableFPElim = true; + m_compiler->getCodeGenOpts().OmitLeafFramePointer = false; + if (generate_debug_info) + m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo); + else + m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo); + + // Disable some warnings. + m_compiler->getDiagnostics().setSeverityForGroup( + clang::diag::Flavor::WarningOrError, "unused-value", + clang::diag::Severity::Ignored, SourceLocation()); + m_compiler->getDiagnostics().setSeverityForGroup( + clang::diag::Flavor::WarningOrError, "odr", + clang::diag::Severity::Ignored, SourceLocation()); + + // Inform the target of the language options + // + // FIXME: We shouldn't need to do this, the target should be immutable once + // created. This complexity should be lifted elsewhere. + m_compiler->getTarget().adjust(m_compiler->getLangOpts()); + + // 6. Set up the diagnostic buffer for reporting errors + + m_compiler->getDiagnostics().setClient(new ClangDiagnosticManagerAdapter); + + // 7. Set up the source management objects inside the compiler + + clang::FileSystemOptions file_system_options; + m_file_manager.reset(new clang::FileManager(file_system_options)); + + if (!m_compiler->hasSourceManager()) + m_compiler->createSourceManager(*m_file_manager.get()); + + m_compiler->createFileManager(); + m_compiler->createPreprocessor(TU_Complete); + + if (ClangModulesDeclVendor *decl_vendor = + target_sp->GetClangModulesDeclVendor()) { + ClangPersistentVariables *clang_persistent_vars = + llvm::cast<ClangPersistentVariables>( + target_sp->GetPersistentExpressionStateForLanguage( + lldb::eLanguageTypeC)); + std::unique_ptr<PPCallbacks> pp_callbacks( + new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars)); + m_pp_callbacks = + static_cast<LLDBPreprocessorCallbacks *>(pp_callbacks.get()); + m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); + } + + // 8. Most of this we get from the CompilerInstance, but we + // also want to give the context an ExternalASTSource. + m_selector_table.reset(new SelectorTable()); + m_builtin_context.reset(new Builtin::Context()); + + std::unique_ptr<clang::ASTContext> ast_context( + new ASTContext(m_compiler->getLangOpts(), m_compiler->getSourceManager(), + m_compiler->getPreprocessor().getIdentifierTable(), + *m_selector_table.get(), *m_builtin_context.get())); + + ast_context->InitBuiltinTypes(m_compiler->getTarget()); + + ClangExpressionHelper *type_system_helper = + dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); + ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); + + if (decl_map) { + llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source( + decl_map->CreateProxy()); + decl_map->InstallASTContext(ast_context.get()); + ast_context->setExternalSource(ast_source); + } + + m_ast_context.reset( + new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str())); + m_ast_context->setASTContext(ast_context.get()); + m_compiler->setASTContext(ast_context.release()); + + std::string module_name("$__lldb_module"); + + m_llvm_context.reset(new LLVMContext()); + m_code_generator.reset(CreateLLVMCodeGen( + m_compiler->getDiagnostics(), module_name, + m_compiler->getHeaderSearchOpts(), m_compiler->getPreprocessorOpts(), + m_compiler->getCodeGenOpts(), *m_llvm_context)); } -unsigned -ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) -{ - ClangDiagnosticManagerAdapter *adapter = - static_cast<ClangDiagnosticManagerAdapter *>(m_compiler->getDiagnostics().getClient()); - clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough(); - diag_buf->FlushDiagnostics(m_compiler->getDiagnostics()); - - adapter->ResetManager(&diagnostic_manager); - - const char *expr_text = m_expr.Text(); - - clang::SourceManager &source_mgr = m_compiler->getSourceManager(); - bool created_main_file = false; - if (m_compiler->getCodeGenOpts().getDebugInfo() == codegenoptions::FullDebugInfo) - { - int temp_fd = -1; - llvm::SmallString<PATH_MAX> result_path; - FileSpec tmpdir_file_spec; - if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - { - tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr"); - std::string temp_source_path = tmpdir_file_spec.GetPath(); - llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path); - } - else - { - llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path); - } - - if (temp_fd != -1) - { - lldb_private::File file(temp_fd, true); - const size_t expr_text_len = strlen(expr_text); - size_t bytes_written = expr_text_len; - if (file.Write(expr_text, bytes_written).Success()) - { - if (bytes_written == expr_text_len) - { - file.Close(); - source_mgr.setMainFileID(source_mgr.createFileID(m_file_manager->getFile(result_path), - SourceLocation(), SrcMgr::C_User)); - created_main_file = true; - } - } +ClangExpressionParser::~ClangExpressionParser() {} + +unsigned ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) { + ClangDiagnosticManagerAdapter *adapter = + static_cast<ClangDiagnosticManagerAdapter *>( + m_compiler->getDiagnostics().getClient()); + clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough(); + diag_buf->FlushDiagnostics(m_compiler->getDiagnostics()); + + adapter->ResetManager(&diagnostic_manager); + + const char *expr_text = m_expr.Text(); + + clang::SourceManager &source_mgr = m_compiler->getSourceManager(); + bool created_main_file = false; + if (m_compiler->getCodeGenOpts().getDebugInfo() == + codegenoptions::FullDebugInfo) { + int temp_fd = -1; + llvm::SmallString<PATH_MAX> result_path; + FileSpec tmpdir_file_spec; + if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, + tmpdir_file_spec)) { + tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr"); + std::string temp_source_path = tmpdir_file_spec.GetPath(); + llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path); + } else { + llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path); + } + + if (temp_fd != -1) { + lldb_private::File file(temp_fd, true); + const size_t expr_text_len = strlen(expr_text); + size_t bytes_written = expr_text_len; + if (file.Write(expr_text, bytes_written).Success()) { + if (bytes_written == expr_text_len) { + file.Close(); + source_mgr.setMainFileID( + source_mgr.createFileID(m_file_manager->getFile(result_path), + SourceLocation(), SrcMgr::C_User)); + created_main_file = true; } + } } + } - if (!created_main_file) - { - std::unique_ptr<MemoryBuffer> memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); - source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer))); - } + if (!created_main_file) { + std::unique_ptr<MemoryBuffer> memory_buffer = + MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); + source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer))); + } - diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); + diag_buf->BeginSourceFile(m_compiler->getLangOpts(), + &m_compiler->getPreprocessor()); - ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); + ClangExpressionHelper *type_system_helper = + dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); - ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get()); + ASTConsumer *ast_transformer = + type_system_helper->ASTTransformer(m_code_generator.get()); - if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap()) - decl_map->InstallCodeGenerator(m_code_generator.get()); + if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap()) + decl_map->InstallCodeGenerator(m_code_generator.get()); - if (ast_transformer) - { - ast_transformer->Initialize(m_compiler->getASTContext()); - ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext()); - } - else - { - m_code_generator->Initialize(m_compiler->getASTContext()); - ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext()); - } + if (ast_transformer) { + ast_transformer->Initialize(m_compiler->getASTContext()); + ParseAST(m_compiler->getPreprocessor(), ast_transformer, + m_compiler->getASTContext()); + } else { + m_code_generator->Initialize(m_compiler->getASTContext()); + ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), + m_compiler->getASTContext()); + } - diag_buf->EndSourceFile(); + diag_buf->EndSourceFile(); - unsigned num_errors = diag_buf->getNumErrors(); + unsigned num_errors = diag_buf->getNumErrors(); - if (m_pp_callbacks && m_pp_callbacks->hasErrors()) - { - num_errors++; - diagnostic_manager.PutCString(eDiagnosticSeverityError, "while importing modules:"); - diagnostic_manager.AppendMessageToDiagnostic(m_pp_callbacks->getErrorString().c_str()); - } + if (m_pp_callbacks && m_pp_callbacks->hasErrors()) { + num_errors++; + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "while importing modules:"); + diagnostic_manager.AppendMessageToDiagnostic( + m_pp_callbacks->getErrorString().c_str()); + } - if (!num_errors) - { - if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't infer the type of a variable"); - num_errors++; - } + if (!num_errors) { + if (type_system_helper->DeclMap() && + !type_system_helper->DeclMap()->ResolveUnknownTypes()) { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Couldn't infer the type of a variable"); + num_errors++; } + } - if (!num_errors) - { - type_system_helper->CommitPersistentDecls(); - } + if (!num_errors) { + type_system_helper->CommitPersistentDecls(); + } - adapter->ResetManager(); + adapter->ResetManager(); - return num_errors; + return num_errors; } std::string -ClangExpressionParser::GetClangTargetABI (const ArchSpec &target_arch) -{ - std::string abi; - - if(target_arch.IsMIPS()) - { - switch (target_arch.GetFlags () & ArchSpec::eMIPSABI_mask) - { - case ArchSpec::eMIPSABI_N64: - abi = "n64"; break; - case ArchSpec::eMIPSABI_N32: - abi = "n32"; break; - case ArchSpec::eMIPSABI_O32: - abi = "o32"; break; - default: - break; - } +ClangExpressionParser::GetClangTargetABI(const ArchSpec &target_arch) { + std::string abi; + + if (target_arch.IsMIPS()) { + switch (target_arch.GetFlags() & ArchSpec::eMIPSABI_mask) { + case ArchSpec::eMIPSABI_N64: + abi = "n64"; + break; + case ArchSpec::eMIPSABI_N32: + abi = "n32"; + break; + case ArchSpec::eMIPSABI_O32: + abi = "o32"; + break; + default: + break; } - return abi; + } + return abi; } -bool -ClangExpressionParser::RewriteExpression(DiagnosticManager &diagnostic_manager) -{ - clang::SourceManager &source_manager = m_compiler->getSourceManager(); - clang::edit::EditedSource editor(source_manager, m_compiler->getLangOpts(), nullptr); - clang::edit::Commit commit(editor); - clang::Rewriter rewriter(source_manager, m_compiler->getLangOpts()); - - class RewritesReceiver : public edit::EditsReceiver { - Rewriter &rewrite; - - public: - RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) { } - - void insert(SourceLocation loc, StringRef text) override { - rewrite.InsertText(loc, text); - } - void replace(CharSourceRange range, StringRef text) override { - rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text); - } - }; - - RewritesReceiver rewrites_receiver(rewriter); - - const DiagnosticList &diagnostics = diagnostic_manager.Diagnostics(); - size_t num_diags = diagnostics.size(); - if (num_diags == 0) - return false; - - for (const Diagnostic *diag : diagnostic_manager.Diagnostics()) - { - const ClangDiagnostic *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag); - if (diagnostic && diagnostic->HasFixIts()) - { - for (const FixItHint &fixit : diagnostic->FixIts()) - { - // This is cobbed from clang::Rewrite::FixItRewriter. - if (fixit.CodeToInsert.empty()) - { - if (fixit.InsertFromRange.isValid()) - { - commit.insertFromRange(fixit.RemoveRange.getBegin(), - fixit.InsertFromRange, /*afterToken=*/false, - fixit.BeforePreviousInsertions); - } - else - commit.remove(fixit.RemoveRange); - } - else - { - if (fixit.RemoveRange.isTokenRange() || - fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) - commit.replace(fixit.RemoveRange, fixit.CodeToInsert); - else - commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert, - /*afterToken=*/false, fixit.BeforePreviousInsertions); - } - } - } +bool ClangExpressionParser::RewriteExpression( + DiagnosticManager &diagnostic_manager) { + clang::SourceManager &source_manager = m_compiler->getSourceManager(); + clang::edit::EditedSource editor(source_manager, m_compiler->getLangOpts(), + nullptr); + clang::edit::Commit commit(editor); + clang::Rewriter rewriter(source_manager, m_compiler->getLangOpts()); + + class RewritesReceiver : public edit::EditsReceiver { + Rewriter &rewrite; + + public: + RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {} + + void insert(SourceLocation loc, StringRef text) override { + rewrite.InsertText(loc, text); } - - // FIXME - do we want to try to propagate specific errors here? - if (!commit.isCommitable()) - return false; - else if (!editor.commit(commit)) - return false; - - // Now play all the edits, and stash the result in the diagnostic manager. - editor.applyRewrites(rewrites_receiver); - RewriteBuffer &main_file_buffer = rewriter.getEditBuffer(source_manager.getMainFileID()); - - std::string fixed_expression; - llvm::raw_string_ostream out_stream(fixed_expression); - - main_file_buffer.write(out_stream); - out_stream.flush(); - diagnostic_manager.SetFixedExpression(fixed_expression); - - return true; -} + void replace(CharSourceRange range, StringRef text) override { + rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text); + } + }; + + RewritesReceiver rewrites_receiver(rewriter); + + const DiagnosticList &diagnostics = diagnostic_manager.Diagnostics(); + size_t num_diags = diagnostics.size(); + if (num_diags == 0) + return false; -static bool FindFunctionInModule (ConstString &mangled_name, - llvm::Module *module, - const char *orig_name) -{ - for (const auto &func : module->getFunctionList()) - { - const StringRef &name = func.getName(); - if (name.find(orig_name) != StringRef::npos) - { - mangled_name.SetString(name); - return true; + for (const Diagnostic *diag : diagnostic_manager.Diagnostics()) { + const ClangDiagnostic *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag); + if (diagnostic && diagnostic->HasFixIts()) { + for (const FixItHint &fixit : diagnostic->FixIts()) { + // This is cobbed from clang::Rewrite::FixItRewriter. + if (fixit.CodeToInsert.empty()) { + if (fixit.InsertFromRange.isValid()) { + commit.insertFromRange(fixit.RemoveRange.getBegin(), + fixit.InsertFromRange, /*afterToken=*/false, + fixit.BeforePreviousInsertions); + } else + commit.remove(fixit.RemoveRange); + } else { + if (fixit.RemoveRange.isTokenRange() || + fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) + commit.replace(fixit.RemoveRange, fixit.CodeToInsert); + else + commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert, + /*afterToken=*/false, fixit.BeforePreviousInsertions); } + } } + } + // FIXME - do we want to try to propagate specific errors here? + if (!commit.isCommitable()) + return false; + else if (!editor.commit(commit)) return false; + + // Now play all the edits, and stash the result in the diagnostic manager. + editor.applyRewrites(rewrites_receiver); + RewriteBuffer &main_file_buffer = + rewriter.getEditBuffer(source_manager.getMainFileID()); + + std::string fixed_expression; + llvm::raw_string_ostream out_stream(fixed_expression); + + main_file_buffer.write(out_stream); + out_stream.flush(); + diagnostic_manager.SetFixedExpression(fixed_expression); + + return true; } -lldb_private::Error -ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, - lldb::addr_t &func_end, - lldb::IRExecutionUnitSP &execution_unit_sp, - ExecutionContext &exe_ctx, - bool &can_interpret, - ExecutionPolicy execution_policy) -{ - func_addr = LLDB_INVALID_ADDRESS; - func_end = LLDB_INVALID_ADDRESS; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - lldb_private::Error err; - - std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule()); - - if (!llvm_module_ap.get()) - { - err.SetErrorToGenericError(); - err.SetErrorString("IR doesn't contain a module"); - return err; +static bool FindFunctionInModule(ConstString &mangled_name, + llvm::Module *module, const char *orig_name) { + for (const auto &func : module->getFunctionList()) { + const StringRef &name = func.getName(); + if (name.find(orig_name) != StringRef::npos) { + mangled_name.SetString(name); + return true; } + } - ConstString function_name; + return false; +} - if (execution_policy != eExecutionPolicyTopLevel) - { - // Find the actual name of the function (it's often mangled somehow) +lldb_private::Error ClangExpressionParser::PrepareForExecution( + lldb::addr_t &func_addr, lldb::addr_t &func_end, + lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx, + bool &can_interpret, ExecutionPolicy execution_policy) { + func_addr = LLDB_INVALID_ADDRESS; + func_end = LLDB_INVALID_ADDRESS; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName())) - { - err.SetErrorToGenericError(); - err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); - return err; - } - else - { - if (log) - log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); - } - } + lldb_private::Error err; - SymbolContext sc; + std::unique_ptr<llvm::Module> llvm_module_ap( + m_code_generator->ReleaseModule()); - if (lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP()) - { - sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything); - } - else if (lldb::TargetSP target_sp = exe_ctx.GetTargetSP()) - { - sc.target_sp = target_sp; - } + if (!llvm_module_ap.get()) { + err.SetErrorToGenericError(); + err.SetErrorString("IR doesn't contain a module"); + return err; + } - LLVMUserExpression::IRPasses custom_passes; - { - auto lang = m_expr.Language(); - if (log) - log->Printf("%s - Currrent expression language is %s\n", __FUNCTION__, - Language::GetNameForLanguageType(lang)); - - if (lang != lldb::eLanguageTypeUnknown) - { - auto runtime = exe_ctx.GetProcessSP()->GetLanguageRuntime(lang); - if (runtime) - runtime->GetIRPasses(custom_passes); - } + ConstString function_name; + + if (execution_policy != eExecutionPolicyTopLevel) { + // Find the actual name of the function (it's often mangled somehow) + + if (!FindFunctionInModule(function_name, llvm_module_ap.get(), + m_expr.FunctionName())) { + err.SetErrorToGenericError(); + err.SetErrorStringWithFormat("Couldn't find %s() in the module", + m_expr.FunctionName()); + return err; + } else { + if (log) + log->Printf("Found function %s for %s", function_name.AsCString(), + m_expr.FunctionName()); } + } + + SymbolContext sc; - if (custom_passes.EarlyPasses) - { - if (log) - log->Printf("%s - Running Early IR Passes from LanguageRuntime on expression module '%s'", __FUNCTION__, - m_expr.FunctionName()); + if (lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP()) { + sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything); + } else if (lldb::TargetSP target_sp = exe_ctx.GetTargetSP()) { + sc.target_sp = target_sp; + } - custom_passes.EarlyPasses->run(*llvm_module_ap); + LLVMUserExpression::IRPasses custom_passes; + { + auto lang = m_expr.Language(); + if (log) + log->Printf("%s - Currrent expression language is %s\n", __FUNCTION__, + Language::GetNameForLanguageType(lang)); + + if (lang != lldb::eLanguageTypeUnknown) { + auto runtime = exe_ctx.GetProcessSP()->GetLanguageRuntime(lang); + if (runtime) + runtime->GetIRPasses(custom_passes); } + } - execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here - llvm_module_ap, // handed off here - function_name, - exe_ctx.GetTargetSP(), - sc, - m_compiler->getTargetOpts().Features)); + if (custom_passes.EarlyPasses) { + if (log) + log->Printf("%s - Running Early IR Passes from LanguageRuntime on " + "expression module '%s'", + __FUNCTION__, m_expr.FunctionName()); - ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); - ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL + custom_passes.EarlyPasses->run(*llvm_module_ap); + } - if (decl_map) - { - Stream *error_stream = NULL; - Target *target = exe_ctx.GetTargetPtr(); - error_stream = target->GetDebugger().GetErrorFile().get(); + execution_unit_sp.reset( + new IRExecutionUnit(m_llvm_context, // handed off here + llvm_module_ap, // handed off here + function_name, exe_ctx.GetTargetSP(), sc, + m_compiler->getTargetOpts().Features)); - IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), *execution_unit_sp, *error_stream, - function_name.AsCString()); + ClangExpressionHelper *type_system_helper = + dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); + ClangExpressionDeclMap *decl_map = + type_system_helper->DeclMap(); // result can be NULL - bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); + if (decl_map) { + Stream *error_stream = NULL; + Target *target = exe_ctx.GetTargetPtr(); + error_stream = target->GetDebugger().GetErrorFile().get(); - if (!ir_can_run) - { - err.SetErrorString("The expression could not be prepared to run in the target"); - return err; - } + IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), + *execution_unit_sp, *error_stream, + function_name.AsCString()); - Process *process = exe_ctx.GetProcessPtr(); + bool ir_can_run = + ir_for_target.runOnModule(*execution_unit_sp->GetModule()); - if (execution_policy != eExecutionPolicyAlways && execution_policy != eExecutionPolicyTopLevel) - { - lldb_private::Error interpret_error; + if (!ir_can_run) { + err.SetErrorString( + "The expression could not be prepared to run in the target"); + return err; + } - bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls(); - can_interpret = - IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), - interpret_error, interpret_function_calls); + Process *process = exe_ctx.GetProcessPtr(); - if (!can_interpret && execution_policy == eExecutionPolicyNever) - { - err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); - return err; - } - } + if (execution_policy != eExecutionPolicyAlways && + execution_policy != eExecutionPolicyTopLevel) { + lldb_private::Error interpret_error; - if (!process && execution_policy == eExecutionPolicyAlways) - { - err.SetErrorString("Expression needed to run in the target, but the target can't be run"); - return err; - } + bool interpret_function_calls = + !process ? false : process->CanInterpretFunctionCalls(); + can_interpret = IRInterpreter::CanInterpret( + *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), + interpret_error, interpret_function_calls); + + if (!can_interpret && execution_policy == eExecutionPolicyNever) { + err.SetErrorStringWithFormat("Can't run the expression locally: %s", + interpret_error.AsCString()); + return err; + } + } + + if (!process && execution_policy == eExecutionPolicyAlways) { + err.SetErrorString("Expression needed to run in the target, but the " + "target can't be run"); + return err; + } + + if (!process && execution_policy == eExecutionPolicyTopLevel) { + err.SetErrorString("Top-level code needs to be inserted into a runnable " + "target, but the target can't be run"); + return err; + } + + if (execution_policy == eExecutionPolicyAlways || + (execution_policy != eExecutionPolicyTopLevel && !can_interpret)) { + if (m_expr.NeedsValidation() && process) { + if (!process->GetDynamicCheckers()) { + DynamicCheckerFunctions *dynamic_checkers = + new DynamicCheckerFunctions(); + + DiagnosticManager install_diagnostics; + + if (!dynamic_checkers->Install(install_diagnostics, exe_ctx)) { + if (install_diagnostics.Diagnostics().size()) + err.SetErrorString("couldn't install checkers, unknown error"); + else + err.SetErrorString(install_diagnostics.GetString().c_str()); - if (!process && execution_policy == eExecutionPolicyTopLevel) - { - err.SetErrorString( - "Top-level code needs to be inserted into a runnable target, but the target can't be run"); return err; + } + + process->SetDynamicCheckers(dynamic_checkers); + + if (log) + log->Printf("== [ClangUserExpression::Evaluate] Finished " + "installing dynamic checkers =="); } - if (execution_policy == eExecutionPolicyAlways || - (execution_policy != eExecutionPolicyTopLevel && !can_interpret)) - { - if (m_expr.NeedsValidation() && process) - { - if (!process->GetDynamicCheckers()) - { - DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); - - DiagnosticManager install_diagnostics; - - if (!dynamic_checkers->Install(install_diagnostics, exe_ctx)) - { - if (install_diagnostics.Diagnostics().size()) - err.SetErrorString("couldn't install checkers, unknown error"); - else - err.SetErrorString(install_diagnostics.GetString().c_str()); - - return err; - } - - process->SetDynamicCheckers(dynamic_checkers); - - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); - } - - IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString()); - - llvm::Module *module = execution_unit_sp->GetModule(); - if (!module || !ir_dynamic_checks.runOnModule(*module)) - { - err.SetErrorToGenericError(); - err.SetErrorString("Couldn't add dynamic checks to the expression"); - return err; - } - - if (custom_passes.LatePasses) - { - if (log) - log->Printf("%s - Running Late IR Passes from LanguageRuntime on expression module '%s'", - __FUNCTION__, m_expr.FunctionName()); - - custom_passes.LatePasses->run(*module); - } - } + IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), + function_name.AsCString()); + + llvm::Module *module = execution_unit_sp->GetModule(); + if (!module || !ir_dynamic_checks.runOnModule(*module)) { + err.SetErrorToGenericError(); + err.SetErrorString("Couldn't add dynamic checks to the expression"); + return err; } - if (execution_policy == eExecutionPolicyAlways || execution_policy == eExecutionPolicyTopLevel || - !can_interpret) - { - execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); + if (custom_passes.LatePasses) { + if (log) + log->Printf("%s - Running Late IR Passes from LanguageRuntime on " + "expression module '%s'", + __FUNCTION__, m_expr.FunctionName()); + + custom_passes.LatePasses->run(*module); } + } } - else - { - execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); + + if (execution_policy == eExecutionPolicyAlways || + execution_policy == eExecutionPolicyTopLevel || !can_interpret) { + execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } + } else { + execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); + } - return err; + return err; } -lldb_private::Error -ClangExpressionParser::RunStaticInitializers (lldb::IRExecutionUnitSP &execution_unit_sp, - ExecutionContext &exe_ctx) -{ - lldb_private::Error err; - - lldbassert(execution_unit_sp.get()); - lldbassert(exe_ctx.HasThreadScope()); - - if (!execution_unit_sp.get()) - { - err.SetErrorString ("can't run static initializers for a NULL execution unit"); - return err; - } - - if (!exe_ctx.HasThreadScope()) - { - err.SetErrorString ("can't run static initializers without a thread"); - return err; - } - - std::vector<lldb::addr_t> static_initializers; - - execution_unit_sp->GetStaticInitializers(static_initializers); - - for (lldb::addr_t static_initializer : static_initializers) - { - EvaluateExpressionOptions options; - - lldb::ThreadPlanSP call_static_initializer(new ThreadPlanCallFunction(exe_ctx.GetThreadRef(), - Address(static_initializer), - CompilerType(), - llvm::ArrayRef<lldb::addr_t>(), - options)); - - DiagnosticManager execution_errors; - lldb::ExpressionResults results = exe_ctx.GetThreadRef().GetProcess()->RunThreadPlan(exe_ctx, call_static_initializer, options, execution_errors); - - if (results != lldb::eExpressionCompleted) - { - err.SetErrorStringWithFormat ("couldn't run static initializer: %s", execution_errors.GetString().c_str()); - return err; - } - } - +lldb_private::Error ClangExpressionParser::RunStaticInitializers( + lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx) { + lldb_private::Error err; + + lldbassert(execution_unit_sp.get()); + lldbassert(exe_ctx.HasThreadScope()); + + if (!execution_unit_sp.get()) { + err.SetErrorString( + "can't run static initializers for a NULL execution unit"); return err; + } + + if (!exe_ctx.HasThreadScope()) { + err.SetErrorString("can't run static initializers without a thread"); + return err; + } + + std::vector<lldb::addr_t> static_initializers; + + execution_unit_sp->GetStaticInitializers(static_initializers); + + for (lldb::addr_t static_initializer : static_initializers) { + EvaluateExpressionOptions options; + + lldb::ThreadPlanSP call_static_initializer(new ThreadPlanCallFunction( + exe_ctx.GetThreadRef(), Address(static_initializer), CompilerType(), + llvm::ArrayRef<lldb::addr_t>(), options)); + + DiagnosticManager execution_errors; + lldb::ExpressionResults results = + exe_ctx.GetThreadRef().GetProcess()->RunThreadPlan( + exe_ctx, call_static_initializer, options, execution_errors); + + if (results != lldb::eExpressionCompleted) { + err.SetErrorStringWithFormat("couldn't run static initializer: %s", + execution_errors.GetString().c_str()); + return err; + } + } + + return err; } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h index 34c0212b73a..3f01156c6de 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -20,13 +20,13 @@ #include <string> #include <vector> -namespace lldb_private -{ +namespace lldb_private { class IRExecutionUnit; - + //---------------------------------------------------------------------- -/// @class ClangExpressionParser ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h" +/// @class ClangExpressionParser ClangExpressionParser.h +/// "lldb/Expression/ClangExpressionParser.h" /// @brief Encapsulates an instance of Clang that can parse expressions. /// /// ClangExpressionParser is responsible for preparing an instance of @@ -35,134 +35,132 @@ class IRExecutionUnit; /// conversion to formats (DWARF bytecode, or JIT compiled machine code) /// that can be executed. //---------------------------------------------------------------------- -class ClangExpressionParser : public ExpressionParser -{ +class ClangExpressionParser : public ExpressionParser { public: - //------------------------------------------------------------------ - /// Constructor - /// - /// Initializes class variables. - /// - /// @param[in] exe_scope, - /// If non-NULL, an execution context scope that can help to - /// correctly create an expression with a valid process for - /// optional tuning Objective-C runtime support. Can be NULL. - /// - /// @param[in] expr - /// The expression to be parsed. - //------------------------------------------------------------------ - ClangExpressionParser (ExecutionContextScope *exe_scope, - Expression &expr, - bool generate_debug_info); - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - ~ClangExpressionParser () override; - - //------------------------------------------------------------------ - /// Parse a single expression and convert it to IR using Clang. Don't - /// wrap the expression in anything at all. - /// - /// @param[in] diagnostic_manager - /// The diagnostic manager to report errors to. - /// - /// @return - /// The number of errors encountered during parsing. 0 means - /// success. - //------------------------------------------------------------------ - unsigned - Parse(DiagnosticManager &diagnostic_manager) override; - - bool - RewriteExpression(DiagnosticManager &diagnostic_manager) override; + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] exe_scope, + /// If non-NULL, an execution context scope that can help to + /// correctly create an expression with a valid process for + /// optional tuning Objective-C runtime support. Can be NULL. + /// + /// @param[in] expr + /// The expression to be parsed. + //------------------------------------------------------------------ + ClangExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, + bool generate_debug_info); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangExpressionParser() override; + + //------------------------------------------------------------------ + /// Parse a single expression and convert it to IR using Clang. Don't + /// wrap the expression in anything at all. + /// + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. + /// + /// @return + /// The number of errors encountered during parsing. 0 means + /// success. + //------------------------------------------------------------------ + unsigned Parse(DiagnosticManager &diagnostic_manager) override; + + bool RewriteExpression(DiagnosticManager &diagnostic_manager) override; - //------------------------------------------------------------------ - /// Ready an already-parsed expression for execution, possibly - /// evaluating it statically. - /// - /// @param[out] func_addr - /// The address to which the function has been written. - /// - /// @param[out] func_end - /// The end of the function's allocated memory region. (func_addr - /// and func_end do not delimit an allocated region; the allocated - /// region may begin before func_addr.) - /// - /// @param[in] execution_unit_sp - /// After parsing, ownership of the execution unit for - /// for the expression is handed to this shared pointer. - /// - /// @param[in] exe_ctx - /// The execution context to write the function into. - /// - /// @param[out] evaluated_statically - /// Set to true if the expression could be interpreted statically; - /// untouched otherwise. - /// - /// @param[out] const_result - /// If the result of the expression is constant, and the - /// expression has no side effects, this is set to the result of the - /// expression. - /// - /// @param[in] execution_policy - /// Determines whether the expression must be JIT-compiled, must be - /// evaluated statically, or whether this decision may be made - /// opportunistically. - /// - /// @return - /// An error code indicating the success or failure of the operation. - /// Test with Success(). - //------------------------------------------------------------------ - Error - PrepareForExecution (lldb::addr_t &func_addr, - lldb::addr_t &func_end, - lldb::IRExecutionUnitSP &execution_unit_sp, - ExecutionContext &exe_ctx, - bool &can_interpret, - lldb_private::ExecutionPolicy execution_policy) override; - - //------------------------------------------------------------------ - /// Run all static initializers for an execution unit. - /// - /// @param[in] execution_unit_sp - /// The execution unit. - /// - /// @param[in] exe_ctx - /// The execution context to use when running them. Thread can't be null. - /// - /// @return - /// The error code indicating the - //------------------------------------------------------------------ - Error - RunStaticInitializers (lldb::IRExecutionUnitSP &execution_unit_sp, - ExecutionContext &exe_ctx); + //------------------------------------------------------------------ + /// Ready an already-parsed expression for execution, possibly + /// evaluating it statically. + /// + /// @param[out] func_addr + /// The address to which the function has been written. + /// + /// @param[out] func_end + /// The end of the function's allocated memory region. (func_addr + /// and func_end do not delimit an allocated region; the allocated + /// region may begin before func_addr.) + /// + /// @param[in] execution_unit_sp + /// After parsing, ownership of the execution unit for + /// for the expression is handed to this shared pointer. + /// + /// @param[in] exe_ctx + /// The execution context to write the function into. + /// + /// @param[out] evaluated_statically + /// Set to true if the expression could be interpreted statically; + /// untouched otherwise. + /// + /// @param[out] const_result + /// If the result of the expression is constant, and the + /// expression has no side effects, this is set to the result of the + /// expression. + /// + /// @param[in] execution_policy + /// Determines whether the expression must be JIT-compiled, must be + /// evaluated statically, or whether this decision may be made + /// opportunistically. + /// + /// @return + /// An error code indicating the success or failure of the operation. + /// Test with Success(). + //------------------------------------------------------------------ + Error + PrepareForExecution(lldb::addr_t &func_addr, lldb::addr_t &func_end, + lldb::IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx, bool &can_interpret, + lldb_private::ExecutionPolicy execution_policy) override; + + //------------------------------------------------------------------ + /// Run all static initializers for an execution unit. + /// + /// @param[in] execution_unit_sp + /// The execution unit. + /// + /// @param[in] exe_ctx + /// The execution context to use when running them. Thread can't be null. + /// + /// @return + /// The error code indicating the + //------------------------------------------------------------------ + Error RunStaticInitializers(lldb::IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Returns a string representing current ABI. + /// + /// @param[in] target_arch + /// The target architecture. + /// + /// @return + /// A string representing target ABI for the current architecture. + //------------------------------------------------------------------- + std::string GetClangTargetABI(const ArchSpec &target_arch); - //------------------------------------------------------------------ - /// Returns a string representing current ABI. - /// - /// @param[in] target_arch - /// The target architecture. - /// - /// @return - /// A string representing target ABI for the current architecture. - //------------------------------------------------------------------- - std::string - GetClangTargetABI (const ArchSpec &target_arch); - private: - std::unique_ptr<llvm::LLVMContext> m_llvm_context; ///< The LLVM context to generate IR into - std::unique_ptr<clang::FileManager> m_file_manager; ///< The Clang file manager object used by the compiler - std::unique_ptr<clang::CompilerInstance> m_compiler; ///< The Clang compiler used to parse expressions into IR - std::unique_ptr<clang::Builtin::Context> m_builtin_context; ///< Context for Clang built-ins - std::unique_ptr<clang::SelectorTable> m_selector_table; ///< Selector table for Objective-C methods - std::unique_ptr<clang::CodeGenerator> m_code_generator; ///< The Clang object that generates IR - - class LLDBPreprocessorCallbacks; - LLDBPreprocessorCallbacks *m_pp_callbacks; ///< Called when the preprocessor encounters module imports - std::unique_ptr<ClangASTContext> m_ast_context; + std::unique_ptr<llvm::LLVMContext> + m_llvm_context; ///< The LLVM context to generate IR into + std::unique_ptr<clang::FileManager> + m_file_manager; ///< The Clang file manager object used by the compiler + std::unique_ptr<clang::CompilerInstance> + m_compiler; ///< The Clang compiler used to parse expressions into IR + std::unique_ptr<clang::Builtin::Context> + m_builtin_context; ///< Context for Clang built-ins + std::unique_ptr<clang::SelectorTable> + m_selector_table; ///< Selector table for Objective-C methods + std::unique_ptr<clang::CodeGenerator> + m_code_generator; ///< The Clang object that generates IR + + class LLDBPreprocessorCallbacks; + LLDBPreprocessorCallbacks *m_pp_callbacks; ///< Called when the preprocessor + ///encounters module imports + std::unique_ptr<ClangASTContext> m_ast_context; }; - } -#endif // liblldb_ClangExpressionParser_h_ +#endif // liblldb_ClangExpressionParser_h_ diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp index 908546b3ecd..ee0c0318256 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp @@ -9,7 +9,6 @@ #include "ClangExpressionVariable.h" -#include "clang/AST/ASTContext.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Stream.h" @@ -17,60 +16,54 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" +#include "clang/AST/ASTContext.h" using namespace lldb_private; using namespace clang; const char *g_clang_expression_variable_kind_name = "ClangExpressionVariable"; -ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size) : - ExpressionVariable(LLVMCastKind::eKindClang), - m_parser_vars(), - m_jit_vars () -{ - m_flags = EVNone; - m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size); +ClangExpressionVariable::ClangExpressionVariable( + ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, + uint32_t addr_byte_size) + : ExpressionVariable(LLVMCastKind::eKindClang), m_parser_vars(), + m_jit_vars() { + m_flags = EVNone; + m_frozen_sp = + ValueObjectConstResult::Create(exe_scope, byte_order, addr_byte_size); } -ClangExpressionVariable::ClangExpressionVariable (ExecutionContextScope *exe_scope, - Value &value, - const ConstString &name, - uint16_t flags) : - ExpressionVariable(LLVMCastKind::eKindClang), - m_parser_vars(), - m_jit_vars () -{ - m_flags = flags; - m_frozen_sp = ValueObjectConstResult::Create (exe_scope, value, name); +ClangExpressionVariable::ClangExpressionVariable( + ExecutionContextScope *exe_scope, Value &value, const ConstString &name, + uint16_t flags) + : ExpressionVariable(LLVMCastKind::eKindClang), m_parser_vars(), + m_jit_vars() { + m_flags = flags; + m_frozen_sp = ValueObjectConstResult::Create(exe_scope, value, name); } -ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) : - ExpressionVariable(LLVMCastKind::eKindClang), - m_parser_vars(), - m_jit_vars () -{ - m_flags = EVNone; - m_frozen_sp = valobj_sp; +ClangExpressionVariable::ClangExpressionVariable( + const lldb::ValueObjectSP &valobj_sp) + : ExpressionVariable(LLVMCastKind::eKindClang), m_parser_vars(), + m_jit_vars() { + m_flags = EVNone; + m_frozen_sp = valobj_sp; } -ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, - const ConstString &name, - const TypeFromUser& user_type, - lldb::ByteOrder byte_order, - uint32_t addr_byte_size) : - ExpressionVariable(LLVMCastKind::eKindClang), - m_parser_vars(), - m_jit_vars() -{ - m_flags = EVNone; - m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size); - SetName (name); - SetCompilerType (user_type); +ClangExpressionVariable::ClangExpressionVariable( + ExecutionContextScope *exe_scope, const ConstString &name, + const TypeFromUser &user_type, lldb::ByteOrder byte_order, + uint32_t addr_byte_size) + : ExpressionVariable(LLVMCastKind::eKindClang), m_parser_vars(), + m_jit_vars() { + m_flags = EVNone; + m_frozen_sp = + ValueObjectConstResult::Create(exe_scope, byte_order, addr_byte_size); + SetName(name); + SetCompilerType(user_type); } -TypeFromUser -ClangExpressionVariable::GetTypeFromUser() -{ - TypeFromUser tfu (m_frozen_sp->GetCompilerType()); - return tfu; +TypeFromUser ClangExpressionVariable::GetTypeFromUser() { + TypeFromUser tfu(m_frozen_sp->GetCompilerType()); + return tfu; } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h index a4596148f6c..c894506a227 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h @@ -24,15 +24,15 @@ #include "llvm/Support/Casting.h" // Project includes -#include "lldb/lldb-public.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Value.h" #include "lldb/Expression/ExpressionVariable.h" #include "lldb/Symbol/TaggedASTType.h" +#include "lldb/lldb-public.h" namespace llvm { - class Value; +class Value; } namespace lldb_private { @@ -40,7 +40,8 @@ namespace lldb_private { class ValueObjectConstResult; //---------------------------------------------------------------------- -/// @class ClangExpressionVariable ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h" +/// @class ClangExpressionVariable ClangExpressionVariable.h +/// "lldb/Expression/ClangExpressionVariable.h" /// @brief Encapsulates one variable for the expression parser. /// /// The expression parser uses variables in three different contexts: @@ -62,204 +63,178 @@ class ValueObjectConstResult; /// polymorphism, and provides necessary support methods. Its interface /// is RTTI-neutral. //---------------------------------------------------------------------- -class ClangExpressionVariable : public ExpressionVariable -{ +class ClangExpressionVariable : public ExpressionVariable { public: - ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size); - - ClangExpressionVariable (ExecutionContextScope *exe_scope, - Value &value, - const ConstString &name, - uint16_t flags = EVNone); - - ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp); - - ClangExpressionVariable(ExecutionContextScope *exe_scope, - const ConstString &name, - const TypeFromUser& user_type, - lldb::ByteOrder byte_order, - uint32_t addr_byte_size); - - //---------------------------------------------------------------------- - /// Utility functions for dealing with ExpressionVariableLists in Clang-specific ways - //---------------------------------------------------------------------- - - //---------------------------------------------------------------------- - /// Finds a variable by NamedDecl in the list. - /// - /// @param[in] name - /// The name of the requested variable. - /// - /// @return - /// The variable requested, or NULL if that variable is not in the list. - //---------------------------------------------------------------------- - static ClangExpressionVariable * - FindVariableInList (ExpressionVariableList &list, const clang::NamedDecl *decl, uint64_t parser_id) - { - lldb::ExpressionVariableSP var_sp; - for (size_t index = 0, size = list.GetSize(); index < size; ++index) - { - var_sp = list.GetVariableAtIndex(index); - - if (ClangExpressionVariable *clang_var = llvm::dyn_cast<ClangExpressionVariable>(var_sp.get())) - { - ClangExpressionVariable::ParserVars *parser_vars = clang_var->GetParserVars(parser_id); - - if (parser_vars && parser_vars->m_named_decl == decl) - return clang_var; - } - } - return nullptr; + ClangExpressionVariable(ExecutionContextScope *exe_scope, + lldb::ByteOrder byte_order, uint32_t addr_byte_size); + + ClangExpressionVariable(ExecutionContextScope *exe_scope, Value &value, + const ConstString &name, uint16_t flags = EVNone); + + ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp); + + ClangExpressionVariable(ExecutionContextScope *exe_scope, + const ConstString &name, + const TypeFromUser &user_type, + lldb::ByteOrder byte_order, uint32_t addr_byte_size); + + //---------------------------------------------------------------------- + /// Utility functions for dealing with ExpressionVariableLists in + /// Clang-specific ways + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + /// Finds a variable by NamedDecl in the list. + /// + /// @param[in] name + /// The name of the requested variable. + /// + /// @return + /// The variable requested, or NULL if that variable is not in the list. + //---------------------------------------------------------------------- + static ClangExpressionVariable * + FindVariableInList(ExpressionVariableList &list, const clang::NamedDecl *decl, + uint64_t parser_id) { + lldb::ExpressionVariableSP var_sp; + for (size_t index = 0, size = list.GetSize(); index < size; ++index) { + var_sp = list.GetVariableAtIndex(index); + + if (ClangExpressionVariable *clang_var = + llvm::dyn_cast<ClangExpressionVariable>(var_sp.get())) { + ClangExpressionVariable::ParserVars *parser_vars = + clang_var->GetParserVars(parser_id); + + if (parser_vars && parser_vars->m_named_decl == decl) + return clang_var; + } } + return nullptr; + } + + //---------------------------------------------------------------------- + /// If the variable contains its own data, make a Value point at it. + /// If \a exe_ctx in not NULL, the value will be resolved in with + /// that execution context. + /// + /// @param[in] value + /// The value to point at the data. + /// + /// @param[in] exe_ctx + /// The execution context to use to resolve \a value. + /// + /// @return + /// True on success; false otherwise (in particular, if this variable + /// does not contain its own data). + //---------------------------------------------------------------------- + bool PointValueAtData(Value &value, ExecutionContext *exe_ctx); + + //---------------------------------------------------------------------- + /// The following values should not live beyond parsing + //---------------------------------------------------------------------- + class ParserVars { + public: + ParserVars() + : m_parser_type(), m_named_decl(NULL), m_llvm_value(NULL), + m_lldb_value(), m_lldb_var(), m_lldb_sym(NULL) {} + + TypeFromParser + m_parser_type; ///< The type of the variable according to the parser + const clang::NamedDecl + *m_named_decl; ///< The Decl corresponding to this variable + llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable; + ///usually a GlobalValue + lldb_private::Value + m_lldb_value; ///< The value found in LLDB for this variable + lldb::VariableSP m_lldb_var; ///< The original variable for this variable + const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this + ///variable, if it was a symbol + }; - //---------------------------------------------------------------------- - /// If the variable contains its own data, make a Value point at it. - /// If \a exe_ctx in not NULL, the value will be resolved in with - /// that execution context. - /// - /// @param[in] value - /// The value to point at the data. - /// - /// @param[in] exe_ctx - /// The execution context to use to resolve \a value. - /// - /// @return - /// True on success; false otherwise (in particular, if this variable - /// does not contain its own data). - //---------------------------------------------------------------------- - bool - PointValueAtData(Value &value, ExecutionContext *exe_ctx); - - //---------------------------------------------------------------------- - /// The following values should not live beyond parsing - //---------------------------------------------------------------------- - class ParserVars - { - public: - - ParserVars() : - m_parser_type(), - m_named_decl (NULL), - m_llvm_value (NULL), - m_lldb_value (), - m_lldb_var (), - m_lldb_sym (NULL) - { - } - - TypeFromParser m_parser_type; ///< The type of the variable according to the parser - const clang::NamedDecl *m_named_decl; ///< The Decl corresponding to this variable - llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable; usually a GlobalValue - lldb_private::Value m_lldb_value; ///< The value found in LLDB for this variable - lldb::VariableSP m_lldb_var; ///< The original variable for this variable - const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this variable, if it was a symbol - }; - private: - typedef std::map <uint64_t, ParserVars> ParserVarMap; - ParserVarMap m_parser_vars; + typedef std::map<uint64_t, ParserVars> ParserVarMap; + ParserVarMap m_parser_vars; public: - //---------------------------------------------------------------------- - /// Make this variable usable by the parser by allocating space for - /// parser-specific variables - //---------------------------------------------------------------------- - void - EnableParserVars(uint64_t parser_id) - { - m_parser_vars.insert(std::make_pair(parser_id, ParserVars())); - } - - //---------------------------------------------------------------------- - /// Deallocate parser-specific variables - //---------------------------------------------------------------------- - void - DisableParserVars(uint64_t parser_id) - { - m_parser_vars.erase(parser_id); - } - - //---------------------------------------------------------------------- - /// Access parser-specific variables - //---------------------------------------------------------------------- - ParserVars * - GetParserVars(uint64_t parser_id) - { - ParserVarMap::iterator i = m_parser_vars.find(parser_id); - - if (i == m_parser_vars.end()) - return NULL; - else - return &i->second; - } - - //---------------------------------------------------------------------- - /// The following values are valid if the variable is used by JIT code - //---------------------------------------------------------------------- - struct JITVars { - JITVars () : - m_alignment (0), - m_size (0), - m_offset (0) - { - } - - lldb::offset_t m_alignment; ///< The required alignment of the variable, in bytes - size_t m_size; ///< The space required for the variable, in bytes - lldb::offset_t m_offset; ///< The offset of the variable in the struct, in bytes - }; - + //---------------------------------------------------------------------- + /// Make this variable usable by the parser by allocating space for + /// parser-specific variables + //---------------------------------------------------------------------- + void EnableParserVars(uint64_t parser_id) { + m_parser_vars.insert(std::make_pair(parser_id, ParserVars())); + } + + //---------------------------------------------------------------------- + /// Deallocate parser-specific variables + //---------------------------------------------------------------------- + void DisableParserVars(uint64_t parser_id) { m_parser_vars.erase(parser_id); } + + //---------------------------------------------------------------------- + /// Access parser-specific variables + //---------------------------------------------------------------------- + ParserVars *GetParserVars(uint64_t parser_id) { + ParserVarMap::iterator i = m_parser_vars.find(parser_id); + + if (i == m_parser_vars.end()) + return NULL; + else + return &i->second; + } + + //---------------------------------------------------------------------- + /// The following values are valid if the variable is used by JIT code + //---------------------------------------------------------------------- + struct JITVars { + JITVars() : m_alignment(0), m_size(0), m_offset(0) {} + + lldb::offset_t + m_alignment; ///< The required alignment of the variable, in bytes + size_t m_size; ///< The space required for the variable, in bytes + lldb::offset_t + m_offset; ///< The offset of the variable in the struct, in bytes + }; + private: - typedef std::map <uint64_t, JITVars> JITVarMap; - JITVarMap m_jit_vars; - + typedef std::map<uint64_t, JITVars> JITVarMap; + JITVarMap m_jit_vars; + public: - //---------------------------------------------------------------------- - /// Make this variable usable for materializing for the JIT by allocating - /// space for JIT-specific variables - //---------------------------------------------------------------------- - void - EnableJITVars(uint64_t parser_id) - { - m_jit_vars.insert(std::make_pair(parser_id, JITVars())); - } - - //---------------------------------------------------------------------- - /// Deallocate JIT-specific variables - //---------------------------------------------------------------------- - void - DisableJITVars(uint64_t parser_id) - { - m_jit_vars.erase(parser_id); - } - - JITVars *GetJITVars(uint64_t parser_id) - { - JITVarMap::iterator i = m_jit_vars.find(parser_id); - - if (i == m_jit_vars.end()) - return NULL; - else - return &i->second; - } - - TypeFromUser - GetTypeFromUser (); - - //------------------------------------------------------------------ - // llvm casting support - //------------------------------------------------------------------ - static bool classof(const ExpressionVariable *ev) - { - return ev->getKind() == ExpressionVariable::eKindClang; - } - - //---------------------------------------------------------------------- - /// Members - //---------------------------------------------------------------------- - DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable); + //---------------------------------------------------------------------- + /// Make this variable usable for materializing for the JIT by allocating + /// space for JIT-specific variables + //---------------------------------------------------------------------- + void EnableJITVars(uint64_t parser_id) { + m_jit_vars.insert(std::make_pair(parser_id, JITVars())); + } + + //---------------------------------------------------------------------- + /// Deallocate JIT-specific variables + //---------------------------------------------------------------------- + void DisableJITVars(uint64_t parser_id) { m_jit_vars.erase(parser_id); } + + JITVars *GetJITVars(uint64_t parser_id) { + JITVarMap::iterator i = m_jit_vars.find(parser_id); + + if (i == m_jit_vars.end()) + return NULL; + else + return &i->second; + } + + TypeFromUser GetTypeFromUser(); + + //------------------------------------------------------------------ + // llvm casting support + //------------------------------------------------------------------ + static bool classof(const ExpressionVariable *ev) { + return ev->getKind() == ExpressionVariable::eKindClang; + } + + //---------------------------------------------------------------------- + /// Members + //---------------------------------------------------------------------- + DISALLOW_COPY_AND_ASSIGN(ClangExpressionVariable); }; } // namespace lldb_private -#endif // liblldb_ClangExpressionVariable_h_ +#endif // liblldb_ClangExpressionVariable_h_ diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp index 02c0ad5013e..87d77386782 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -50,178 +50,177 @@ using namespace lldb_private; //---------------------------------------------------------------------- // ClangFunctionCaller constructor //---------------------------------------------------------------------- -ClangFunctionCaller::ClangFunctionCaller -( - ExecutionContextScope &exe_scope, - const CompilerType &return_type, - const Address& functionAddress, - const ValueList &arg_value_list, - const char *name -) : - FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list, name), - m_type_system_helper (*this) -{ - m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); - // Can't make a ClangFunctionCaller without a process. - assert (m_jit_process_wp.lock()); +ClangFunctionCaller::ClangFunctionCaller(ExecutionContextScope &exe_scope, + const CompilerType &return_type, + const Address &functionAddress, + const ValueList &arg_value_list, + const char *name) + : FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list, + name), + m_type_system_helper(*this) { + m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); + // Can't make a ClangFunctionCaller without a process. + assert(m_jit_process_wp.lock()); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -ClangFunctionCaller::~ClangFunctionCaller() -{ -} +ClangFunctionCaller::~ClangFunctionCaller() {} unsigned -ClangFunctionCaller::CompileFunction (lldb::ThreadSP thread_to_use_sp, - DiagnosticManager &diagnostic_manager) -{ - if (m_compiled) - return 0; - - // Compilation might call code, make sure to keep on the thread the caller indicated. - ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(thread_to_use_sp); - - // FIXME: How does clang tell us there's no return value? We need to handle that case. - unsigned num_errors = 0; - - std::string return_type_str (m_function_return_type.GetTypeName().AsCString("")); - - // Cons up the function we're going to wrap our call in, then compile it... - // We declare the function "extern "C"" because the compiler might be in C++ - // mode which would mangle the name and then we couldn't find it again... - m_wrapper_function_text.clear(); - m_wrapper_function_text.append ("extern \"C\" void "); - m_wrapper_function_text.append (m_wrapper_function_name); - m_wrapper_function_text.append (" (void *input)\n{\n struct "); - m_wrapper_function_text.append (m_wrapper_struct_name); - m_wrapper_function_text.append (" \n {\n"); - m_wrapper_function_text.append (" "); - m_wrapper_function_text.append (return_type_str); - m_wrapper_function_text.append (" (*fn_ptr) ("); - - // Get the number of arguments. If we have a function type and it is prototyped, - // trust that, otherwise use the values we were given. - - // FIXME: This will need to be extended to handle Variadic functions. We'll need - // to pull the defined arguments out of the function, then add the types from the - // arguments list for the variable arguments. - - uint32_t num_args = UINT32_MAX; - bool trust_function = false; - // GetArgumentCount returns -1 for an unprototyped function. - CompilerType function_clang_type; - if (m_function_ptr) - { - function_clang_type = m_function_ptr->GetCompilerType(); - if (function_clang_type) - { - int num_func_args = function_clang_type.GetFunctionArgumentCount(); - if (num_func_args >= 0) - { - trust_function = true; - num_args = num_func_args; - } - } - } - - if (num_args == UINT32_MAX) - num_args = m_arg_values.GetSize(); - - std::string args_buffer; // This one stores the definition of all the args in "struct caller". - std::string args_list_buffer; // This one stores the argument list called from the structure. - for (size_t i = 0; i < num_args; i++) - { - std::string type_name; - - if (trust_function) - { - type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString(""); - } - else - { - CompilerType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetCompilerType (); - if (clang_qual_type) - { - type_name = clang_qual_type.GetTypeName().AsCString(""); - } - else - { - diagnostic_manager.Printf(eDiagnosticSeverityError, - "Could not determine type of input value %" PRIu64 ".", (uint64_t)i); - return 1; - } - } - - m_wrapper_function_text.append (type_name); - if (i < num_args - 1) - m_wrapper_function_text.append (", "); - - char arg_buf[32]; - args_buffer.append (" "); - args_buffer.append (type_name); - snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i); - args_buffer.push_back (' '); - args_buffer.append (arg_buf); - args_buffer.append (";\n"); - - args_list_buffer.append ("__lldb_fn_data->"); - args_list_buffer.append (arg_buf); - if (i < num_args - 1) - args_list_buffer.append (", "); - +ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp, + DiagnosticManager &diagnostic_manager) { + if (m_compiled) + return 0; + + // Compilation might call code, make sure to keep on the thread the caller + // indicated. + ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher( + thread_to_use_sp); + + // FIXME: How does clang tell us there's no return value? We need to handle + // that case. + unsigned num_errors = 0; + + std::string return_type_str( + m_function_return_type.GetTypeName().AsCString("")); + + // Cons up the function we're going to wrap our call in, then compile it... + // We declare the function "extern "C"" because the compiler might be in C++ + // mode which would mangle the name and then we couldn't find it again... + m_wrapper_function_text.clear(); + m_wrapper_function_text.append("extern \"C\" void "); + m_wrapper_function_text.append(m_wrapper_function_name); + m_wrapper_function_text.append(" (void *input)\n{\n struct "); + m_wrapper_function_text.append(m_wrapper_struct_name); + m_wrapper_function_text.append(" \n {\n"); + m_wrapper_function_text.append(" "); + m_wrapper_function_text.append(return_type_str); + m_wrapper_function_text.append(" (*fn_ptr) ("); + + // Get the number of arguments. If we have a function type and it is + // prototyped, + // trust that, otherwise use the values we were given. + + // FIXME: This will need to be extended to handle Variadic functions. We'll + // need + // to pull the defined arguments out of the function, then add the types from + // the + // arguments list for the variable arguments. + + uint32_t num_args = UINT32_MAX; + bool trust_function = false; + // GetArgumentCount returns -1 for an unprototyped function. + CompilerType function_clang_type; + if (m_function_ptr) { + function_clang_type = m_function_ptr->GetCompilerType(); + if (function_clang_type) { + int num_func_args = function_clang_type.GetFunctionArgumentCount(); + if (num_func_args >= 0) { + trust_function = true; + num_args = num_func_args; + } } - m_wrapper_function_text.append (");\n"); // Close off the function calling prototype. - - m_wrapper_function_text.append (args_buffer); - - m_wrapper_function_text.append (" "); - m_wrapper_function_text.append (return_type_str); - m_wrapper_function_text.append (" return_value;"); - m_wrapper_function_text.append ("\n };\n struct "); - m_wrapper_function_text.append (m_wrapper_struct_name); - m_wrapper_function_text.append ("* __lldb_fn_data = (struct "); - m_wrapper_function_text.append (m_wrapper_struct_name); - m_wrapper_function_text.append (" *) input;\n"); - - m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr ("); - m_wrapper_function_text.append (args_list_buffer); - m_wrapper_function_text.append (");\n}\n"); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); - - // Okay, now compile this expression - - lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); - if (jit_process_sp) - { - const bool generate_debug_info = true; - m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info)); - - num_errors = m_parser->Parse(diagnostic_manager); + } + + if (num_args == UINT32_MAX) + num_args = m_arg_values.GetSize(); + + std::string args_buffer; // This one stores the definition of all the args in + // "struct caller". + std::string args_list_buffer; // This one stores the argument list called from + // the structure. + for (size_t i = 0; i < num_args; i++) { + std::string type_name; + + if (trust_function) { + type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i) + .GetTypeName() + .AsCString(""); + } else { + CompilerType clang_qual_type = + m_arg_values.GetValueAtIndex(i)->GetCompilerType(); + if (clang_qual_type) { + type_name = clang_qual_type.GetTypeName().AsCString(""); + } else { + diagnostic_manager.Printf( + eDiagnosticSeverityError, + "Could not determine type of input value %" PRIu64 ".", + (uint64_t)i); + return 1; + } } - else - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, "no process - unable to inject function"); - num_errors = 1; - } - - m_compiled = (num_errors == 0); - - if (!m_compiled) - return num_errors; + m_wrapper_function_text.append(type_name); + if (i < num_args - 1) + m_wrapper_function_text.append(", "); + + char arg_buf[32]; + args_buffer.append(" "); + args_buffer.append(type_name); + snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i); + args_buffer.push_back(' '); + args_buffer.append(arg_buf); + args_buffer.append(";\n"); + + args_list_buffer.append("__lldb_fn_data->"); + args_list_buffer.append(arg_buf); + if (i < num_args - 1) + args_list_buffer.append(", "); + } + m_wrapper_function_text.append( + ");\n"); // Close off the function calling prototype. + + m_wrapper_function_text.append(args_buffer); + + m_wrapper_function_text.append(" "); + m_wrapper_function_text.append(return_type_str); + m_wrapper_function_text.append(" return_value;"); + m_wrapper_function_text.append("\n };\n struct "); + m_wrapper_function_text.append(m_wrapper_struct_name); + m_wrapper_function_text.append("* __lldb_fn_data = (struct "); + m_wrapper_function_text.append(m_wrapper_struct_name); + m_wrapper_function_text.append(" *) input;\n"); + + m_wrapper_function_text.append( + " __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr ("); + m_wrapper_function_text.append(args_list_buffer); + m_wrapper_function_text.append(");\n}\n"); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + if (log) + log->Printf("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); + + // Okay, now compile this expression + + lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); + if (jit_process_sp) { + const bool generate_debug_info = true; + m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, + generate_debug_info)); + + num_errors = m_parser->Parse(diagnostic_manager); + } else { + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "no process - unable to inject function"); + num_errors = 1; + } + + m_compiled = (num_errors == 0); + + if (!m_compiled) return num_errors; + + return num_errors; } clang::ASTConsumer * -ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer (clang::ASTConsumer *passthrough) -{ - m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_owner.GetWrapperStructName(), m_owner)); - - return m_struct_extractor.get(); +ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer( + clang::ASTConsumer *passthrough) { + m_struct_extractor.reset(new ASTStructExtractor( + passthrough, m_owner.GetWrapperStructName(), m_owner)); + + return m_struct_extractor.get(); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h index 468b9c1c76d..56d1d8412f7 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -16,23 +16,23 @@ // Project includes #include "ClangExpressionHelper.h" -#include "lldb/Core/ClangForward.h" #include "lldb/Core/Address.h" #include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ClangForward.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectList.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Process.h" -namespace lldb_private -{ - +namespace lldb_private { + class ASTStructExtractor; class ClangExpressionParser; //---------------------------------------------------------------------- -/// @class ClangFunctionCaller ClangFunctionCaller.h "lldb/Expression/ClangFunctionCaller.h" +/// @class ClangFunctionCaller ClangFunctionCaller.h +/// "lldb/Expression/ClangFunctionCaller.h" /// @brief Encapsulates a function that can be called. /// /// A given ClangFunctionCaller object can handle a single function signature. @@ -42,7 +42,7 @@ class ClangExpressionParser; /// It performs the call by synthesizing a structure that contains the pointer /// to the function and the arguments that should be passed to that function, /// and producing a special-purpose JIT-compiled function that accepts a void* -/// pointing to this struct as its only argument and calls the function in the +/// pointing to this struct as its only argument and calls the function in the /// struct with the written arguments. This method lets Clang handle the /// vagaries of function calling conventions. /// @@ -54,124 +54,111 @@ class ClangExpressionParser; /// InsertFunction() followed by WriteFunctionArguments(), which will return /// the location of the args struct for the wrapper function in args_addr_ref. /// -/// If you need to call the function on the thread plan stack, you can also +/// If you need to call the function on the thread plan stack, you can also /// call InsertFunction() followed by GetThreadPlanToCallFunction(). /// /// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed /// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated /// and its address returned in that variable. -/// +/// /// Any of the methods that take arg_addr_ptr can be passed NULL, and the /// argument space will be managed for you. -//---------------------------------------------------------------------- -class ClangFunctionCaller : public FunctionCaller -{ - friend class ASTStructExtractor; - - class ClangFunctionCallerHelper : public ClangExpressionHelper - { - public: - ClangFunctionCallerHelper (ClangFunctionCaller &owner) : - m_owner(owner) - { - } - - ~ClangFunctionCallerHelper() override = default; - - //------------------------------------------------------------------ - /// Return the object that the parser should use when resolving external - /// values. May be NULL if everything should be self-contained. - //------------------------------------------------------------------ - ClangExpressionDeclMap * - DeclMap() override - { - return NULL; - } - - //------------------------------------------------------------------ - /// Return the object that the parser should allow to access ASTs. - /// May be NULL if the ASTs do not need to be transformed. - /// - /// @param[in] passthrough - /// The ASTConsumer that the returned transformer should send - /// the ASTs to after transformation. - //------------------------------------------------------------------ - clang::ASTConsumer * - ASTTransformer(clang::ASTConsumer *passthrough) override; - - private: - ClangFunctionCaller &m_owner; - std::unique_ptr<ASTStructExtractor> m_struct_extractor; ///< The class that generates the argument struct layout. - }; +//---------------------------------------------------------------------- +class ClangFunctionCaller : public FunctionCaller { + friend class ASTStructExtractor; + + class ClangFunctionCallerHelper : public ClangExpressionHelper { + public: + ClangFunctionCallerHelper(ClangFunctionCaller &owner) : m_owner(owner) {} + + ~ClangFunctionCallerHelper() override = default; -public: //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] exe_scope - /// An execution context scope that gets us at least a target and - /// process. - /// - /// @param[in] ast_context - /// The AST context to evaluate argument types in. - /// - /// @param[in] return_qualtype - /// An opaque Clang QualType for the function result. Should be - /// defined in ast_context. - /// - /// @param[in] function_address - /// The address of the function to call. - /// - /// @param[in] arg_value_list - /// The default values to use when calling this function. Can - /// be overridden using WriteFunctionArguments(). + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. //------------------------------------------------------------------ - ClangFunctionCaller (ExecutionContextScope &exe_scope, - const CompilerType &return_type, - const Address& function_address, - const ValueList &arg_value_list, - const char *name); - - ~ClangFunctionCaller() override; + ClangExpressionDeclMap *DeclMap() override { return NULL; } //------------------------------------------------------------------ - /// Compile the wrapper function - /// - /// @param[in] thread_to_use_sp - /// Compilation might end up calling functions. Pass in the thread you - /// want the compilation to use. If you pass in an empty ThreadSP it will - /// use the currently selected thread. + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. /// - /// @param[in] diagnostic_manager - /// The diagnostic manager to report parser errors to. - /// - /// @return - /// The number of errors. + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. //------------------------------------------------------------------ - unsigned - CompileFunction (lldb::ThreadSP thread_to_use_sp, - DiagnosticManager &diagnostic_manager) override; + clang::ASTConsumer * + ASTTransformer(clang::ASTConsumer *passthrough) override; + + private: + ClangFunctionCaller &m_owner; + std::unique_ptr<ASTStructExtractor> m_struct_extractor; ///< The class that + ///generates the + ///argument struct + ///layout. + }; - ExpressionTypeSystemHelper * - GetTypeSystemHelper() override - { - return &m_type_system_helper; - } +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] exe_scope + /// An execution context scope that gets us at least a target and + /// process. + /// + /// @param[in] ast_context + /// The AST context to evaluate argument types in. + /// + /// @param[in] return_qualtype + /// An opaque Clang QualType for the function result. Should be + /// defined in ast_context. + /// + /// @param[in] function_address + /// The address of the function to call. + /// + /// @param[in] arg_value_list + /// The default values to use when calling this function. Can + /// be overridden using WriteFunctionArguments(). + //------------------------------------------------------------------ + ClangFunctionCaller(ExecutionContextScope &exe_scope, + const CompilerType &return_type, + const Address &function_address, + const ValueList &arg_value_list, const char *name); + + ~ClangFunctionCaller() override; + + //------------------------------------------------------------------ + /// Compile the wrapper function + /// + /// @param[in] thread_to_use_sp + /// Compilation might end up calling functions. Pass in the thread you + /// want the compilation to use. If you pass in an empty ThreadSP it will + /// use the currently selected thread. + /// + /// @param[in] diagnostic_manager + /// The diagnostic manager to report parser errors to. + /// + /// @return + /// The number of errors. + //------------------------------------------------------------------ + unsigned CompileFunction(lldb::ThreadSP thread_to_use_sp, + DiagnosticManager &diagnostic_manager) override; + + ExpressionTypeSystemHelper *GetTypeSystemHelper() override { + return &m_type_system_helper; + } protected: - const char *GetWrapperStructName() - { - return m_wrapper_struct_name.c_str(); - } + const char *GetWrapperStructName() { return m_wrapper_struct_name.c_str(); } private: - //------------------------------------------------------------------ - // For ClangFunctionCaller only - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // For ClangFunctionCaller only + //------------------------------------------------------------------ - // Note: the parser needs to be destructed before the execution unit, so - // declare the execution unit first. - ClangFunctionCallerHelper m_type_system_helper; + // Note: the parser needs to be destructed before the execution unit, so + // declare the execution unit first. + ClangFunctionCallerHelper m_type_system_helper; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index eed63dcc34c..3c21de241c4 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -37,700 +37,643 @@ using namespace lldb_private; namespace { - // Any Clang compiler requires a consumer for diagnostics. This one stores them as strings - // so we can provide them to the user in case a module failed to load. - class StoringDiagnosticConsumer : public clang::DiagnosticConsumer - { - public: - StoringDiagnosticConsumer (); - - void - HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, - const clang::Diagnostic &info) override; - - void - ClearDiagnostics (); - - void - DumpDiagnostics (Stream &error_stream); - - private: - typedef std::pair<clang::DiagnosticsEngine::Level, std::string> IDAndDiagnostic; - std::vector<IDAndDiagnostic> m_diagnostics; - Log * m_log; - }; - - // The private implementation of our ClangModulesDeclVendor. Contains all the Clang state required - // to load modules. - class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor - { - public: - ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine, - llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation, - std::unique_ptr<clang::CompilerInstance> &&compiler_instance, - std::unique_ptr<clang::Parser> &&parser); - - ~ClangModulesDeclVendorImpl() override = default; - - bool - AddModule(ModulePath &path, - ModuleVector *exported_modules, - Stream &error_stream) override; - - bool - AddModulesForCompileUnit(CompileUnit &cu, - ModuleVector &exported_modules, - Stream &error_stream) override; - - uint32_t - FindDecls(const ConstString &name, - bool append, - uint32_t max_matches, - std::vector <clang::NamedDecl*> &decls) override; - - void - ForEachMacro(const ModuleVector &modules, - std::function<bool (const std::string &)> handler) override; - - private: - void - ReportModuleExportsHelper (std::set<ClangModulesDeclVendor::ModuleID> &exports, - clang::Module *module); - - void - ReportModuleExports (ModuleVector &exports, - clang::Module *module); - - clang::ModuleLoadResult - DoGetModule(clang::ModuleIdPath path, bool make_visible); - - bool m_enabled = false; - - llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> m_diagnostics_engine; - llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> m_compiler_invocation; - std::unique_ptr<clang::CompilerInstance> m_compiler_instance; - std::unique_ptr<clang::Parser> m_parser; - size_t m_source_location_index = 0; // used to give name components fake SourceLocations - - typedef std::vector<ConstString> ImportedModule; - typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap; - typedef std::set<ModuleID> ImportedModuleSet; - ImportedModuleMap m_imported_modules; - ImportedModuleSet m_user_imported_modules; - }; +// Any Clang compiler requires a consumer for diagnostics. This one stores them +// as strings +// so we can provide them to the user in case a module failed to load. +class StoringDiagnosticConsumer : public clang::DiagnosticConsumer { +public: + StoringDiagnosticConsumer(); + + void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, + const clang::Diagnostic &info) override; + + void ClearDiagnostics(); + + void DumpDiagnostics(Stream &error_stream); + +private: + typedef std::pair<clang::DiagnosticsEngine::Level, std::string> + IDAndDiagnostic; + std::vector<IDAndDiagnostic> m_diagnostics; + Log *m_log; +}; + +// The private implementation of our ClangModulesDeclVendor. Contains all the +// Clang state required +// to load modules. +class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor { +public: + ClangModulesDeclVendorImpl( + llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine, + llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation, + std::unique_ptr<clang::CompilerInstance> &&compiler_instance, + std::unique_ptr<clang::Parser> &&parser); + + ~ClangModulesDeclVendorImpl() override = default; + + bool AddModule(ModulePath &path, ModuleVector *exported_modules, + Stream &error_stream) override; + + bool AddModulesForCompileUnit(CompileUnit &cu, ModuleVector &exported_modules, + Stream &error_stream) override; + + uint32_t FindDecls(const ConstString &name, bool append, uint32_t max_matches, + std::vector<clang::NamedDecl *> &decls) override; + + void ForEachMacro(const ModuleVector &modules, + std::function<bool(const std::string &)> handler) override; + +private: + void + ReportModuleExportsHelper(std::set<ClangModulesDeclVendor::ModuleID> &exports, + clang::Module *module); + + void ReportModuleExports(ModuleVector &exports, clang::Module *module); + + clang::ModuleLoadResult DoGetModule(clang::ModuleIdPath path, + bool make_visible); + + bool m_enabled = false; + + llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> m_diagnostics_engine; + llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> m_compiler_invocation; + std::unique_ptr<clang::CompilerInstance> m_compiler_instance; + std::unique_ptr<clang::Parser> m_parser; + size_t m_source_location_index = + 0; // used to give name components fake SourceLocations + + typedef std::vector<ConstString> ImportedModule; + typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap; + typedef std::set<ModuleID> ImportedModuleSet; + ImportedModuleMap m_imported_modules; + ImportedModuleSet m_user_imported_modules; +}; } // anonymous namespace -StoringDiagnosticConsumer::StoringDiagnosticConsumer () -{ - m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); +StoringDiagnosticConsumer::StoringDiagnosticConsumer() { + m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); } -void -StoringDiagnosticConsumer::HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) -{ - llvm::SmallVector<char, 256> diagnostic_string; - - info.FormatDiagnostic(diagnostic_string); - - m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(), diagnostic_string.size()))); -} +void StoringDiagnosticConsumer::HandleDiagnostic( + clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) { + llvm::SmallVector<char, 256> diagnostic_string; -void -StoringDiagnosticConsumer::ClearDiagnostics () -{ - m_diagnostics.clear(); + info.FormatDiagnostic(diagnostic_string); + + m_diagnostics.push_back( + IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(), + diagnostic_string.size()))); } -void -StoringDiagnosticConsumer::DumpDiagnostics (Stream &error_stream) -{ - for (IDAndDiagnostic &diag : m_diagnostics) - { - switch (diag.first) - { - default: - error_stream.PutCString(diag.second.c_str()); - error_stream.PutChar('\n'); - break; - case clang::DiagnosticsEngine::Level::Ignored: - break; - } +void StoringDiagnosticConsumer::ClearDiagnostics() { m_diagnostics.clear(); } + +void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) { + for (IDAndDiagnostic &diag : m_diagnostics) { + switch (diag.first) { + default: + error_stream.PutCString(diag.second.c_str()); + error_stream.PutChar('\n'); + break; + case clang::DiagnosticsEngine::Level::Ignored: + break; } + } } -static FileSpec -GetResourceDir () -{ - static FileSpec g_cached_resource_dir; - - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, [](){ - HostInfo::GetLLDBPath (lldb::ePathTypeClangDir, g_cached_resource_dir); - }); - - return g_cached_resource_dir; -} +static FileSpec GetResourceDir() { + static FileSpec g_cached_resource_dir; -ClangModulesDeclVendor::ClangModulesDeclVendor() -{ -} + static std::once_flag g_once_flag; -ClangModulesDeclVendor::~ClangModulesDeclVendor() -{ -} + std::call_once(g_once_flag, []() { + HostInfo::GetLLDBPath(lldb::ePathTypeClangDir, g_cached_resource_dir); + }); -ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine, - llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation, - std::unique_ptr<clang::CompilerInstance> &&compiler_instance, - std::unique_ptr<clang::Parser> &&parser) : - ClangModulesDeclVendor(), - m_diagnostics_engine(diagnostics_engine), - m_compiler_invocation(compiler_invocation), - m_compiler_instance(std::move(compiler_instance)), - m_parser(std::move(parser)), - m_imported_modules() -{ + return g_cached_resource_dir; } -void -ClangModulesDeclVendorImpl::ReportModuleExportsHelper (std::set<ClangModulesDeclVendor::ModuleID> &exports, - clang::Module *module) -{ - if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module))) - return; - - exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)); - - llvm::SmallVector<clang::Module*, 2> sub_exports; - - module->getExportedModules(sub_exports); - - for (clang::Module *module : sub_exports) - { - ReportModuleExportsHelper(exports, module); - } +ClangModulesDeclVendor::ClangModulesDeclVendor() {} + +ClangModulesDeclVendor::~ClangModulesDeclVendor() {} + +ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl( + llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine, + llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation, + std::unique_ptr<clang::CompilerInstance> &&compiler_instance, + std::unique_ptr<clang::Parser> &&parser) + : ClangModulesDeclVendor(), m_diagnostics_engine(diagnostics_engine), + m_compiler_invocation(compiler_invocation), + m_compiler_instance(std::move(compiler_instance)), + m_parser(std::move(parser)), m_imported_modules() {} + +void ClangModulesDeclVendorImpl::ReportModuleExportsHelper( + std::set<ClangModulesDeclVendor::ModuleID> &exports, + clang::Module *module) { + if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module))) + return; + + exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)); + + llvm::SmallVector<clang::Module *, 2> sub_exports; + + module->getExportedModules(sub_exports); + + for (clang::Module *module : sub_exports) { + ReportModuleExportsHelper(exports, module); + } } -void -ClangModulesDeclVendorImpl::ReportModuleExports (ClangModulesDeclVendor::ModuleVector &exports, - clang::Module *module) -{ - std::set<ClangModulesDeclVendor::ModuleID> exports_set; - - ReportModuleExportsHelper(exports_set, module); - - for (ModuleID module : exports_set) - { - exports.push_back(module); - } +void ClangModulesDeclVendorImpl::ReportModuleExports( + ClangModulesDeclVendor::ModuleVector &exports, clang::Module *module) { + std::set<ClangModulesDeclVendor::ModuleID> exports_set; + + ReportModuleExportsHelper(exports_set, module); + + for (ModuleID module : exports_set) { + exports.push_back(module); + } } -bool -ClangModulesDeclVendorImpl::AddModule(ModulePath &path, - ModuleVector *exported_modules, - Stream &error_stream) -{ - // Fail early. - - if (m_compiler_instance->hadModuleLoaderFatalFailure()) - { - error_stream.PutCString("error: Couldn't load a module because the module loader is in a fatal state.\n"); - return false; - } - - // Check if we've already imported this module. - - std::vector<ConstString> imported_module; - - for (ConstString path_component : path) - { - imported_module.push_back(path_component); - } - - { - ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module); - - if (mi != m_imported_modules.end()) - { - if (exported_modules) - { - ReportModuleExports(*exported_modules, mi->second); - } - return true; - } - } - - if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0].GetStringRef())) - { - error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].AsCString()); - return false; - } - - llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>, 4> clang_path; - - { - clang::SourceManager &source_manager = m_compiler_instance->getASTContext().getSourceManager(); - - for (ConstString path_component : path) - { - clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(path_component.GetStringRef()), - source_manager.getLocForStartOfFile(source_manager.getMainFileID()).getLocWithOffset(m_source_location_index++))); - } +bool ClangModulesDeclVendorImpl::AddModule(ModulePath &path, + ModuleVector *exported_modules, + Stream &error_stream) { + // Fail early. + + if (m_compiler_instance->hadModuleLoaderFatalFailure()) { + error_stream.PutCString("error: Couldn't load a module because the module " + "loader is in a fatal state.\n"); + return false; + } + + // Check if we've already imported this module. + + std::vector<ConstString> imported_module; + + for (ConstString path_component : path) { + imported_module.push_back(path_component); + } + + { + ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module); + + if (mi != m_imported_modules.end()) { + if (exported_modules) { + ReportModuleExports(*exported_modules, mi->second); + } + return true; } - - StoringDiagnosticConsumer *diagnostic_consumer = static_cast<StoringDiagnosticConsumer *>(m_compiler_instance->getDiagnostics().getClient()); - - diagnostic_consumer->ClearDiagnostics(); - - clang::Module *top_level_module = DoGetModule(clang_path.front(), false); - - if (!top_level_module) - { - diagnostic_consumer->DumpDiagnostics(error_stream); - error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].AsCString()); - return false; + } + + if (!m_compiler_instance->getPreprocessor() + .getHeaderSearchInfo() + .lookupModule(path[0].GetStringRef())) { + error_stream.Printf("error: Header search couldn't locate module %s\n", + path[0].AsCString()); + return false; + } + + llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>, + 4> + clang_path; + + { + clang::SourceManager &source_manager = + m_compiler_instance->getASTContext().getSourceManager(); + + for (ConstString path_component : path) { + clang_path.push_back(std::make_pair( + &m_compiler_instance->getASTContext().Idents.get( + path_component.GetStringRef()), + source_manager.getLocForStartOfFile(source_manager.getMainFileID()) + .getLocWithOffset(m_source_location_index++))); } - - clang::Module *submodule = top_level_module; - - for (size_t ci = 1; ci < path.size(); ++ci) - { - llvm::StringRef component = path[ci].GetStringRef(); - submodule = submodule->findSubmodule(component.str()); - if (!submodule) - { - diagnostic_consumer->DumpDiagnostics(error_stream); - error_stream.Printf("error: Couldn't load submodule %s\n", component.str().c_str()); - return false; - } + } + + StoringDiagnosticConsumer *diagnostic_consumer = + static_cast<StoringDiagnosticConsumer *>( + m_compiler_instance->getDiagnostics().getClient()); + + diagnostic_consumer->ClearDiagnostics(); + + clang::Module *top_level_module = DoGetModule(clang_path.front(), false); + + if (!top_level_module) { + diagnostic_consumer->DumpDiagnostics(error_stream); + error_stream.Printf("error: Couldn't load top-level module %s\n", + path[0].AsCString()); + return false; + } + + clang::Module *submodule = top_level_module; + + for (size_t ci = 1; ci < path.size(); ++ci) { + llvm::StringRef component = path[ci].GetStringRef(); + submodule = submodule->findSubmodule(component.str()); + if (!submodule) { + diagnostic_consumer->DumpDiagnostics(error_stream); + error_stream.Printf("error: Couldn't load submodule %s\n", + component.str().c_str()); + return false; } - - clang::Module *requested_module = DoGetModule(clang_path, true); - - if (requested_module != nullptr) - { - if (exported_modules) - { - ReportModuleExports(*exported_modules, requested_module); - } + } + + clang::Module *requested_module = DoGetModule(clang_path, true); - m_imported_modules[imported_module] = requested_module; - - m_enabled = true; - - return true; + if (requested_module != nullptr) { + if (exported_modules) { + ReportModuleExports(*exported_modules, requested_module); } - - return false; + + m_imported_modules[imported_module] = requested_module; + + m_enabled = true; + + return true; + } + + return false; } -bool -ClangModulesDeclVendor::LanguageSupportsClangModules (lldb::LanguageType language) -{ - switch (language) - { - default: - return false; - // C++ and friends to be added - case lldb::LanguageType::eLanguageTypeC: - case lldb::LanguageType::eLanguageTypeC11: - case lldb::LanguageType::eLanguageTypeC89: - case lldb::LanguageType::eLanguageTypeC99: - case lldb::LanguageType::eLanguageTypeObjC: - return true; - } +bool ClangModulesDeclVendor::LanguageSupportsClangModules( + lldb::LanguageType language) { + switch (language) { + default: + return false; + // C++ and friends to be added + case lldb::LanguageType::eLanguageTypeC: + case lldb::LanguageType::eLanguageTypeC11: + case lldb::LanguageType::eLanguageTypeC89: + case lldb::LanguageType::eLanguageTypeC99: + case lldb::LanguageType::eLanguageTypeObjC: + return true; + } } -bool -ClangModulesDeclVendorImpl::AddModulesForCompileUnit(CompileUnit &cu, - ClangModulesDeclVendor::ModuleVector &exported_modules, - Stream &error_stream) -{ - if (LanguageSupportsClangModules(cu.GetLanguage())) - { - std::vector<ConstString> imported_modules = cu.GetImportedModules(); - - for (ConstString imported_module : imported_modules) - { - std::vector<ConstString> path; - - path.push_back(imported_module); - - if (!AddModule(path, &exported_modules, error_stream)) - { - return false; - } - } - - return true; +bool ClangModulesDeclVendorImpl::AddModulesForCompileUnit( + CompileUnit &cu, ClangModulesDeclVendor::ModuleVector &exported_modules, + Stream &error_stream) { + if (LanguageSupportsClangModules(cu.GetLanguage())) { + std::vector<ConstString> imported_modules = cu.GetImportedModules(); + + for (ConstString imported_module : imported_modules) { + std::vector<ConstString> path; + + path.push_back(imported_module); + + if (!AddModule(path, &exported_modules, error_stream)) { + return false; + } } return true; + } + + return true; } // ClangImporter::lookupValue uint32_t -ClangModulesDeclVendorImpl::FindDecls (const ConstString &name, - bool append, - uint32_t max_matches, - std::vector <clang::NamedDecl*> &decls) -{ - if (!m_enabled) - { - return 0; - } +ClangModulesDeclVendorImpl::FindDecls(const ConstString &name, bool append, + uint32_t max_matches, + std::vector<clang::NamedDecl *> &decls) { + if (!m_enabled) { + return 0; + } - if (!append) - decls.clear(); - - clang::IdentifierInfo &ident = m_compiler_instance->getASTContext().Idents.get(name.GetStringRef()); - - clang::LookupResult lookup_result(m_compiler_instance->getSema(), - clang::DeclarationName(&ident), - clang::SourceLocation(), - clang::Sema::LookupOrdinaryName); - - m_compiler_instance->getSema().LookupName(lookup_result, m_compiler_instance->getSema().getScopeForContext(m_compiler_instance->getASTContext().getTranslationUnitDecl())); - - uint32_t num_matches = 0; - - for (clang::NamedDecl *named_decl : lookup_result) - { - if (num_matches >= max_matches) - return num_matches; - - decls.push_back(named_decl); - ++num_matches; - } - - return num_matches; + if (!append) + decls.clear(); + + clang::IdentifierInfo &ident = + m_compiler_instance->getASTContext().Idents.get(name.GetStringRef()); + + clang::LookupResult lookup_result( + m_compiler_instance->getSema(), clang::DeclarationName(&ident), + clang::SourceLocation(), clang::Sema::LookupOrdinaryName); + + m_compiler_instance->getSema().LookupName( + lookup_result, + m_compiler_instance->getSema().getScopeForContext( + m_compiler_instance->getASTContext().getTranslationUnitDecl())); + + uint32_t num_matches = 0; + + for (clang::NamedDecl *named_decl : lookup_result) { + if (num_matches >= max_matches) + return num_matches; + + decls.push_back(named_decl); + ++num_matches; + } + + return num_matches; } -void -ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVector &modules, - std::function<bool (const std::string &)> handler) -{ - if (!m_enabled) - { - return; - } - - typedef std::map<ModuleID, ssize_t> ModulePriorityMap; - ModulePriorityMap module_priorities; - - ssize_t priority = 0; - - for (ModuleID module : modules) +void ClangModulesDeclVendorImpl::ForEachMacro( + const ClangModulesDeclVendor::ModuleVector &modules, + std::function<bool(const std::string &)> handler) { + if (!m_enabled) { + return; + } + + typedef std::map<ModuleID, ssize_t> ModulePriorityMap; + ModulePriorityMap module_priorities; + + ssize_t priority = 0; + + for (ModuleID module : modules) { + module_priorities[module] = priority++; + } + + if (m_compiler_instance->getPreprocessor().getExternalSource()) { + m_compiler_instance->getPreprocessor() + .getExternalSource() + ->ReadDefinedMacros(); + } + + for (clang::Preprocessor::macro_iterator + mi = m_compiler_instance->getPreprocessor().macro_begin(), + me = m_compiler_instance->getPreprocessor().macro_end(); + mi != me; ++mi) { + const clang::IdentifierInfo *ii = nullptr; + { - module_priorities[module] = priority++; + if (clang::IdentifierInfoLookup *lookup = + m_compiler_instance->getPreprocessor() + .getIdentifierTable() + .getExternalIdentifierLookup()) { + lookup->get(mi->first->getName()); + } + if (!ii) { + ii = mi->first; + } } - - if (m_compiler_instance->getPreprocessor().getExternalSource()) - { - m_compiler_instance->getPreprocessor().getExternalSource()->ReadDefinedMacros(); + + ssize_t found_priority = -1; + clang::MacroInfo *macro_info = nullptr; + + for (clang::ModuleMacro *module_macro : + m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) { + clang::Module *module = module_macro->getOwningModule(); + + { + ModulePriorityMap::iterator pi = + module_priorities.find(reinterpret_cast<ModuleID>(module)); + + if (pi != module_priorities.end() && pi->second > found_priority) { + macro_info = module_macro->getMacroInfo(); + found_priority = pi->second; + } + } + + clang::Module *top_level_module = module->getTopLevelModule(); + + if (top_level_module != module) { + ModulePriorityMap::iterator pi = module_priorities.find( + reinterpret_cast<ModuleID>(top_level_module)); + + if ((pi != module_priorities.end()) && pi->second > found_priority) { + macro_info = module_macro->getMacroInfo(); + found_priority = pi->second; + } + } } - - for (clang::Preprocessor::macro_iterator mi = m_compiler_instance->getPreprocessor().macro_begin(), - me = m_compiler_instance->getPreprocessor().macro_end(); - mi != me; - ++mi) - { - const clang::IdentifierInfo *ii = nullptr; - - { - if (clang::IdentifierInfoLookup *lookup = m_compiler_instance->getPreprocessor().getIdentifierTable().getExternalIdentifierLookup()) - { - lookup->get(mi->first->getName()); + + if (macro_info) { + std::string macro_expansion = "#define "; + macro_expansion.append(mi->first->getName().str().c_str()); + + { + if (macro_info->isFunctionLike()) { + macro_expansion.append("("); + + bool first_arg = true; + + for (clang::MacroInfo::arg_iterator ai = macro_info->arg_begin(), + ae = macro_info->arg_end(); + ai != ae; ++ai) { + if (!first_arg) { + macro_expansion.append(", "); + } else { + first_arg = false; } - if (!ii) - { - ii = mi->first; + + macro_expansion.append((*ai)->getName().str()); + } + + if (macro_info->isC99Varargs()) { + if (first_arg) { + macro_expansion.append("..."); + } else { + macro_expansion.append(", ..."); } + } else if (macro_info->isGNUVarargs()) { + macro_expansion.append("..."); + } + + macro_expansion.append(")"); } - - ssize_t found_priority = -1; - clang::MacroInfo *macro_info = nullptr; - - for (clang::ModuleMacro *module_macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) - { - clang::Module *module = module_macro->getOwningModule(); - - { - ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(module)); - - if (pi != module_priorities.end() && pi->second > found_priority) - { - macro_info = module_macro->getMacroInfo(); - found_priority = pi->second; - } + + macro_expansion.append(" "); + + bool first_token = true; + + for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(), + te = macro_info->tokens_end(); + ti != te; ++ti) { + if (!first_token) { + macro_expansion.append(" "); + } else { + first_token = false; + } + + if (ti->isLiteral()) { + if (const char *literal_data = ti->getLiteralData()) { + std::string token_str(literal_data, ti->getLength()); + macro_expansion.append(token_str); + } else { + bool invalid = false; + const char *literal_source = + m_compiler_instance->getSourceManager().getCharacterData( + ti->getLocation(), &invalid); + + if (invalid) { + lldbassert(!"Unhandled token kind"); + macro_expansion.append("<unknown literal value>"); + } else { + macro_expansion.append( + std::string(literal_source, ti->getLength())); + } } - - clang::Module *top_level_module = module->getTopLevelModule(); - - if (top_level_module != module) - { - ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(top_level_module)); - - if ((pi != module_priorities.end()) && pi->second > found_priority) - { - macro_info = module_macro->getMacroInfo(); - found_priority = pi->second; - } + } else if (const char *punctuator_spelling = + clang::tok::getPunctuatorSpelling(ti->getKind())) { + macro_expansion.append(punctuator_spelling); + } else if (const char *keyword_spelling = + clang::tok::getKeywordSpelling(ti->getKind())) { + macro_expansion.append(keyword_spelling); + } else { + switch (ti->getKind()) { + case clang::tok::TokenKind::identifier: + macro_expansion.append(ti->getIdentifierInfo()->getName().str()); + break; + case clang::tok::TokenKind::raw_identifier: + macro_expansion.append(ti->getRawIdentifier().str()); + break; + default: + macro_expansion.append(ti->getName()); + break; } + } } - - if (macro_info) - { - std::string macro_expansion = "#define "; - macro_expansion.append(mi->first->getName().str().c_str()); - - { - if (macro_info->isFunctionLike()) - { - macro_expansion.append("("); - - bool first_arg = true; - - for (clang::MacroInfo::arg_iterator ai = macro_info->arg_begin(), - ae = macro_info->arg_end(); - ai != ae; - ++ai) - { - if (!first_arg) - { - macro_expansion.append(", "); - } - else - { - first_arg = false; - } - - macro_expansion.append((*ai)->getName().str()); - } - - if (macro_info->isC99Varargs()) - { - if (first_arg) - { - macro_expansion.append("..."); - } - else - { - macro_expansion.append(", ..."); - } - } - else if (macro_info->isGNUVarargs()) - { - macro_expansion.append("..."); - } - - macro_expansion.append(")"); - } - - macro_expansion.append(" "); - - bool first_token = true; - - for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(), - te = macro_info->tokens_end(); - ti != te; - ++ti) - { - if (!first_token) - { - macro_expansion.append(" "); - } - else - { - first_token = false; - } - - if (ti->isLiteral()) - { - if (const char *literal_data = ti->getLiteralData()) - { - std::string token_str(literal_data, ti->getLength()); - macro_expansion.append(token_str); - } - else - { - bool invalid = false; - const char *literal_source = m_compiler_instance->getSourceManager().getCharacterData(ti->getLocation(), &invalid); - - if (invalid) - { - lldbassert(!"Unhandled token kind"); - macro_expansion.append("<unknown literal value>"); - } - else - { - macro_expansion.append(std::string(literal_source, ti->getLength())); - } - } - } - else if (const char *punctuator_spelling = clang::tok::getPunctuatorSpelling(ti->getKind())) - { - macro_expansion.append(punctuator_spelling); - } - else if (const char *keyword_spelling = clang::tok::getKeywordSpelling(ti->getKind())) - { - macro_expansion.append(keyword_spelling); - } - else - { - switch (ti->getKind()) - { - case clang::tok::TokenKind::identifier: - macro_expansion.append(ti->getIdentifierInfo()->getName().str()); - break; - case clang::tok::TokenKind::raw_identifier: - macro_expansion.append(ti->getRawIdentifier().str()); - break; - default: - macro_expansion.append(ti->getName()); - break; - } - } - } - - if (handler(macro_expansion)) - { - return; - } - } + + if (handler(macro_expansion)) { + return; } + } } + } } clang::ModuleLoadResult ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, - bool make_visible) -{ - clang::Module::NameVisibilityKind visibility = make_visible ? clang::Module::AllVisible : clang::Module::Hidden; - - const bool is_inclusion_directive = false; - - return m_compiler_instance->loadModule(path.front().second, path, visibility, is_inclusion_directive); + bool make_visible) { + clang::Module::NameVisibilityKind visibility = + make_visible ? clang::Module::AllVisible : clang::Module::Hidden; + + const bool is_inclusion_directive = false; + + return m_compiler_instance->loadModule(path.front().second, path, visibility, + is_inclusion_directive); } static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; lldb_private::ClangModulesDeclVendor * -ClangModulesDeclVendor::Create(Target &target) -{ - // FIXME we should insure programmatically that the expression parser's compiler and the modules runtime's - // compiler are both initialized in the same way – preferably by the same code. - - if (!target.GetPlatform()->SupportsModules()) - return nullptr; - - const ArchSpec &arch = target.GetArchitecture(); - - std::vector<std::string> compiler_invocation_arguments = - { - "clang", - "-fmodules", - "-fimplicit-module-maps", - "-fcxx-modules", - "-fsyntax-only", - "-femit-all-decls", - "-target", arch.GetTriple().str(), - "-fmodules-validate-system-headers", - "-Werror=non-modular-include-in-framework-module" - }; - - target.GetPlatform()->AddClangModuleCompilationOptions(&target, compiler_invocation_arguments); - - compiler_invocation_arguments.push_back(ModuleImportBufferName); - - // Add additional search paths with { "-I", path } or { "-F", path } here. - - { - llvm::SmallString<128> DefaultModuleCache; - const bool erased_on_reboot = false; - llvm::sys::path::system_temp_directory(erased_on_reboot, DefaultModuleCache); - llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); - llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); - std::string module_cache_argument("-fmodules-cache-path="); - module_cache_argument.append(DefaultModuleCache.str().str()); - compiler_invocation_arguments.push_back(module_cache_argument); +ClangModulesDeclVendor::Create(Target &target) { + // FIXME we should insure programmatically that the expression parser's + // compiler and the modules runtime's + // compiler are both initialized in the same way – preferably by the same + // code. + + if (!target.GetPlatform()->SupportsModules()) + return nullptr; + + const ArchSpec &arch = target.GetArchitecture(); + + std::vector<std::string> compiler_invocation_arguments = { + "clang", + "-fmodules", + "-fimplicit-module-maps", + "-fcxx-modules", + "-fsyntax-only", + "-femit-all-decls", + "-target", + arch.GetTriple().str(), + "-fmodules-validate-system-headers", + "-Werror=non-modular-include-in-framework-module"}; + + target.GetPlatform()->AddClangModuleCompilationOptions( + &target, compiler_invocation_arguments); + + compiler_invocation_arguments.push_back(ModuleImportBufferName); + + // Add additional search paths with { "-I", path } or { "-F", path } here. + + { + llvm::SmallString<128> DefaultModuleCache; + const bool erased_on_reboot = false; + llvm::sys::path::system_temp_directory(erased_on_reboot, + DefaultModuleCache); + llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); + llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); + std::string module_cache_argument("-fmodules-cache-path="); + module_cache_argument.append(DefaultModuleCache.str().str()); + compiler_invocation_arguments.push_back(module_cache_argument); + } + + FileSpecList &module_search_paths = target.GetClangModuleSearchPaths(); + + for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi) { + const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi); + + std::string search_path_argument = "-I"; + search_path_argument.append(search_path.GetPath()); + + compiler_invocation_arguments.push_back(search_path_argument); + } + + { + FileSpec clang_resource_dir = GetResourceDir(); + + if (clang_resource_dir.IsDirectory()) { + compiler_invocation_arguments.push_back("-resource-dir"); + compiler_invocation_arguments.push_back(clang_resource_dir.GetPath()); } - - FileSpecList &module_search_paths = target.GetClangModuleSearchPaths(); - - for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi) - { - const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi); - - std::string search_path_argument = "-I"; - search_path_argument.append(search_path.GetPath()); - - compiler_invocation_arguments.push_back(search_path_argument); - } - - { - FileSpec clang_resource_dir = GetResourceDir(); - - if (clang_resource_dir.IsDirectory()) - { - compiler_invocation_arguments.push_back("-resource-dir"); - compiler_invocation_arguments.push_back(clang_resource_dir.GetPath()); - } - } - - llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine = clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions, - new StoringDiagnosticConsumer); - - std::vector<const char *> compiler_invocation_argument_cstrs; - - for (const std::string &arg : compiler_invocation_arguments) { - compiler_invocation_argument_cstrs.push_back(arg.c_str()); - } - - llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> invocation(clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs, diagnostics_engine)); - - if (!invocation) - return nullptr; - - std::unique_ptr<llvm::MemoryBuffer> source_buffer = llvm::MemoryBuffer::getMemBuffer("extern int __lldb __attribute__((unavailable));", - ModuleImportBufferName); - - invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, source_buffer.release()); - - std::unique_ptr<clang::CompilerInstance> instance(new clang::CompilerInstance); - - instance->setDiagnostics(diagnostics_engine.get()); - instance->setInvocation(invocation.get()); - - std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction); - - instance->setTarget(clang::TargetInfo::CreateTargetInfo(*diagnostics_engine, instance->getInvocation().TargetOpts)); - - if (!instance->hasTarget()) - return nullptr; - - instance->getTarget().adjust(instance->getLangOpts()); - - if (!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0])) - return nullptr; - - instance->getPreprocessor().enableIncrementalProcessing(); - - instance->createModuleManager(); - - instance->createSema(action->getTranslationUnitKind(), nullptr); - - const bool skipFunctionBodies = false; - std::unique_ptr<clang::Parser> parser(new clang::Parser(instance->getPreprocessor(), instance->getSema(), skipFunctionBodies)); - - instance->getPreprocessor().EnterMainSourceFile(); - parser->Initialize(); - - clang::Parser::DeclGroupPtrTy parsed; - - while (!parser->ParseTopLevelDecl(parsed)); - - return new ClangModulesDeclVendorImpl (diagnostics_engine, invocation, std::move(instance), std::move(parser)); + } + + llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine = + clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions, + new StoringDiagnosticConsumer); + + std::vector<const char *> compiler_invocation_argument_cstrs; + + for (const std::string &arg : compiler_invocation_arguments) { + compiler_invocation_argument_cstrs.push_back(arg.c_str()); + } + + llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> invocation( + clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs, + diagnostics_engine)); + + if (!invocation) + return nullptr; + + std::unique_ptr<llvm::MemoryBuffer> source_buffer = + llvm::MemoryBuffer::getMemBuffer( + "extern int __lldb __attribute__((unavailable));", + ModuleImportBufferName); + + invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, + source_buffer.release()); + + std::unique_ptr<clang::CompilerInstance> instance( + new clang::CompilerInstance); + + instance->setDiagnostics(diagnostics_engine.get()); + instance->setInvocation(invocation.get()); + + std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction); + + instance->setTarget(clang::TargetInfo::CreateTargetInfo( + *diagnostics_engine, instance->getInvocation().TargetOpts)); + + if (!instance->hasTarget()) + return nullptr; + + instance->getTarget().adjust(instance->getLangOpts()); + + if (!action->BeginSourceFile(*instance, + instance->getFrontendOpts().Inputs[0])) + return nullptr; + + instance->getPreprocessor().enableIncrementalProcessing(); + + instance->createModuleManager(); + + instance->createSema(action->getTranslationUnitKind(), nullptr); + + const bool skipFunctionBodies = false; + std::unique_ptr<clang::Parser> parser(new clang::Parser( + instance->getPreprocessor(), instance->getSema(), skipFunctionBodies)); + + instance->getPreprocessor().EnterMainSourceFile(); + parser->Initialize(); + + clang::Parser::DeclGroupPtrTy parsed; + + while (!parser->ParseTopLevelDecl(parsed)) + ; + + return new ClangModulesDeclVendorImpl(diagnostics_engine, invocation, + std::move(instance), std::move(parser)); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h index df3b20550f9..fbabcd73686 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h @@ -18,111 +18,104 @@ #include <set> #include <vector> -namespace lldb_private -{ - -class ClangModulesDeclVendor : public DeclVendor -{ +namespace lldb_private { + +class ClangModulesDeclVendor : public DeclVendor { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - ClangModulesDeclVendor(); - - ~ClangModulesDeclVendor() override; - - static ClangModulesDeclVendor * - Create(Target &target); - - typedef std::vector<ConstString> ModulePath; - typedef uintptr_t ModuleID; - typedef std::vector<ModuleID> ModuleVector; - - //------------------------------------------------------------------ - /// Add a module to the list of modules to search. - /// - /// @param[in] path - /// The path to the exact module to be loaded. E.g., if the desired - /// module is std.io, then this should be { "std", "io" }. - /// - /// @param[in] exported_modules - /// If non-NULL, a pointer to a vector to populate with the ID of every - /// module that is re-exported by the specified module. - /// - /// @param[in] error_stream - /// A stream to populate with the output of the Clang parser when - /// it tries to load the module. - /// - /// @return - /// True if the module could be loaded; false if not. If the - /// compiler encountered a fatal error during a previous module - /// load, then this will always return false for this ModuleImporter. - //------------------------------------------------------------------ - virtual bool - AddModule(ModulePath &path, - ModuleVector *exported_modules, - Stream &error_stream) = 0; - - //------------------------------------------------------------------ - /// Add all modules referred to in a given compilation unit to the list - /// of modules to search. - /// - /// @param[in] cu - /// The compilation unit to scan for imported modules. - /// - /// @param[in] exported_modules - /// A vector to populate with the ID of each module loaded (directly - /// and via re-exports) in this way. - /// - /// @param[in] error_stream - /// A stream to populate with the output of the Clang parser when - /// it tries to load the modules. - /// - /// @return - /// True if all modules referred to by the compilation unit could be - /// loaded; false if one could not be loaded. If the compiler - /// encountered a fatal error during a previous module - /// load, then this will always return false for this ModuleImporter. - //------------------------------------------------------------------ - virtual bool - AddModulesForCompileUnit(CompileUnit &cu, - ModuleVector &exported_modules, - Stream &error_stream) = 0; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ClangModulesDeclVendor(); + + ~ClangModulesDeclVendor() override; + + static ClangModulesDeclVendor *Create(Target &target); + + typedef std::vector<ConstString> ModulePath; + typedef uintptr_t ModuleID; + typedef std::vector<ModuleID> ModuleVector; - //------------------------------------------------------------------ - /// Enumerate all the macros that are defined by a given set of modules - /// that are already imported. - /// - /// @param[in] modules - /// The unique IDs for all modules to query. Later modules have higher - /// priority, just as if you @imported them in that order. This matters - /// if module A #defines a macro and module B #undefs it. - /// - /// @param[in] handler - /// A function to call with the text of each #define (including the - /// #define directive). #undef directives are not included; we simply - /// elide any corresponding #define. If this function returns true, - /// we stop the iteration immediately. - //------------------------------------------------------------------ - virtual void - ForEachMacro(const ModuleVector &modules, - std::function<bool (const std::string &)> handler) = 0; - - //------------------------------------------------------------------ - /// Query whether Clang supports modules for a particular language. - /// LLDB uses this to decide whether to try to find the modules loaded - /// by a gaiven compile unit. - /// - /// @param[in] language - /// The language to query for. - /// - /// @return - /// True if Clang has modules for the given language. - //------------------------------------------------------------------ - static bool - LanguageSupportsClangModules (lldb::LanguageType language); + //------------------------------------------------------------------ + /// Add a module to the list of modules to search. + /// + /// @param[in] path + /// The path to the exact module to be loaded. E.g., if the desired + /// module is std.io, then this should be { "std", "io" }. + /// + /// @param[in] exported_modules + /// If non-NULL, a pointer to a vector to populate with the ID of every + /// module that is re-exported by the specified module. + /// + /// @param[in] error_stream + /// A stream to populate with the output of the Clang parser when + /// it tries to load the module. + /// + /// @return + /// True if the module could be loaded; false if not. If the + /// compiler encountered a fatal error during a previous module + /// load, then this will always return false for this ModuleImporter. + //------------------------------------------------------------------ + virtual bool AddModule(ModulePath &path, ModuleVector *exported_modules, + Stream &error_stream) = 0; + + //------------------------------------------------------------------ + /// Add all modules referred to in a given compilation unit to the list + /// of modules to search. + /// + /// @param[in] cu + /// The compilation unit to scan for imported modules. + /// + /// @param[in] exported_modules + /// A vector to populate with the ID of each module loaded (directly + /// and via re-exports) in this way. + /// + /// @param[in] error_stream + /// A stream to populate with the output of the Clang parser when + /// it tries to load the modules. + /// + /// @return + /// True if all modules referred to by the compilation unit could be + /// loaded; false if one could not be loaded. If the compiler + /// encountered a fatal error during a previous module + /// load, then this will always return false for this ModuleImporter. + //------------------------------------------------------------------ + virtual bool AddModulesForCompileUnit(CompileUnit &cu, + ModuleVector &exported_modules, + Stream &error_stream) = 0; + + //------------------------------------------------------------------ + /// Enumerate all the macros that are defined by a given set of modules + /// that are already imported. + /// + /// @param[in] modules + /// The unique IDs for all modules to query. Later modules have higher + /// priority, just as if you @imported them in that order. This matters + /// if module A #defines a macro and module B #undefs it. + /// + /// @param[in] handler + /// A function to call with the text of each #define (including the + /// #define directive). #undef directives are not included; we simply + /// elide any corresponding #define. If this function returns true, + /// we stop the iteration immediately. + //------------------------------------------------------------------ + virtual void + ForEachMacro(const ModuleVector &modules, + std::function<bool(const std::string &)> handler) = 0; + + //------------------------------------------------------------------ + /// Query whether Clang supports modules for a particular language. + /// LLDB uses this to decide whether to try to find the modules loaded + /// by a gaiven compile unit. + /// + /// @param[in] language + /// The language to query for. + /// + /// @return + /// True if Clang has modules for the given language. + //------------------------------------------------------------------ + static bool LanguageSupportsClangModules(lldb::LanguageType language); }; - + } // namespace lldb_private #endif // liblldb_ClangModulesDeclVendor_h diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp index d1478e49bff..4d30956177d 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -21,74 +21,66 @@ using namespace lldb; using namespace lldb_private; -ClangPersistentVariables::ClangPersistentVariables () : - lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang), - m_next_persistent_variable_id (0) -{ -} +ClangPersistentVariables::ClangPersistentVariables() + : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang), + m_next_persistent_variable_id(0) {} -ExpressionVariableSP -ClangPersistentVariables::CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) -{ - return AddNewlyConstructedVariable(new ClangExpressionVariable(valobj_sp)); +ExpressionVariableSP ClangPersistentVariables::CreatePersistentVariable( + const lldb::ValueObjectSP &valobj_sp) { + return AddNewlyConstructedVariable(new ClangExpressionVariable(valobj_sp)); } -ExpressionVariableSP -ClangPersistentVariables::CreatePersistentVariable (ExecutionContextScope *exe_scope, - const ConstString &name, - const CompilerType& compiler_type, - lldb::ByteOrder byte_order, - uint32_t addr_byte_size) -{ - return AddNewlyConstructedVariable(new ClangExpressionVariable(exe_scope, name, compiler_type, byte_order, addr_byte_size)); +ExpressionVariableSP ClangPersistentVariables::CreatePersistentVariable( + ExecutionContextScope *exe_scope, const ConstString &name, + const CompilerType &compiler_type, lldb::ByteOrder byte_order, + uint32_t addr_byte_size) { + return AddNewlyConstructedVariable(new ClangExpressionVariable( + exe_scope, name, compiler_type, byte_order, addr_byte_size)); } -void -ClangPersistentVariables::RemovePersistentVariable (lldb::ExpressionVariableSP variable) -{ - RemoveVariable(variable); - - const char *name = variable->GetName().AsCString(); - - if (*name != '$') - return; - name++; - - if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1) - m_next_persistent_variable_id--; +void ClangPersistentVariables::RemovePersistentVariable( + lldb::ExpressionVariableSP variable) { + RemoveVariable(variable); + + const char *name = variable->GetName().AsCString(); + + if (*name != '$') + return; + name++; + + if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1) + m_next_persistent_variable_id--; } -ConstString -ClangPersistentVariables::GetNextPersistentVariableName () -{ - char name_cstr[256]; - ::snprintf (name_cstr, sizeof(name_cstr), "$%u", m_next_persistent_variable_id++); - ConstString name(name_cstr); - return name; +ConstString ClangPersistentVariables::GetNextPersistentVariableName() { + char name_cstr[256]; + ::snprintf(name_cstr, sizeof(name_cstr), "$%u", + m_next_persistent_variable_id++); + ConstString name(name_cstr); + return name; } -void -ClangPersistentVariables::RegisterPersistentDecl (const ConstString &name, - clang::NamedDecl *decl) -{ - m_persistent_decls.insert(std::pair<const char*, clang::NamedDecl*>(name.GetCString(), decl)); - - if (clang::EnumDecl *enum_decl = llvm::dyn_cast<clang::EnumDecl>(decl)) - { - for (clang::EnumConstantDecl *enumerator_decl : enum_decl->enumerators()) - { - m_persistent_decls.insert(std::pair<const char*, clang::NamedDecl*>(ConstString(enumerator_decl->getNameAsString()).GetCString(), enumerator_decl)); - } +void ClangPersistentVariables::RegisterPersistentDecl(const ConstString &name, + clang::NamedDecl *decl) { + m_persistent_decls.insert( + std::pair<const char *, clang::NamedDecl *>(name.GetCString(), decl)); + + if (clang::EnumDecl *enum_decl = llvm::dyn_cast<clang::EnumDecl>(decl)) { + for (clang::EnumConstantDecl *enumerator_decl : enum_decl->enumerators()) { + m_persistent_decls.insert(std::pair<const char *, clang::NamedDecl *>( + ConstString(enumerator_decl->getNameAsString()).GetCString(), + enumerator_decl)); } + } } clang::NamedDecl * -ClangPersistentVariables::GetPersistentDecl (const ConstString &name) -{ - PersistentDeclMap::const_iterator i = m_persistent_decls.find(name.GetCString()); - - if (i == m_persistent_decls.end()) - return NULL; - else - return i->second; +ClangPersistentVariables::GetPersistentDecl(const ConstString &name) { + PersistentDeclMap::const_iterator i = + m_persistent_decls.find(name.GetCString()); + + if (i == m_persistent_decls.end()) + return NULL; + else + return i->second; } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h index 2928976592d..16981a7fe14 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -21,81 +21,74 @@ #include "lldb/Expression/ExpressionVariable.h" -namespace lldb_private -{ - +namespace lldb_private { + //---------------------------------------------------------------------- -/// @class ClangPersistentVariables ClangPersistentVariables.h "lldb/Expression/ClangPersistentVariables.h" -/// @brief Manages persistent values that need to be preserved between expression invocations. +/// @class ClangPersistentVariables ClangPersistentVariables.h +/// "lldb/Expression/ClangPersistentVariables.h" +/// @brief Manages persistent values that need to be preserved between +/// expression invocations. /// /// A list of variables that can be accessed and updated by any expression. See /// ClangPersistentVariable for more discussion. Also provides an increasing, /// 0-based counter for naming result variables. //---------------------------------------------------------------------- -class ClangPersistentVariables : public PersistentExpressionState -{ +class ClangPersistentVariables : public PersistentExpressionState { public: - ClangPersistentVariables(); - - ~ClangPersistentVariables() override = default; - - //------------------------------------------------------------------ - // llvm casting support - //------------------------------------------------------------------ - static bool classof(const PersistentExpressionState *pv) - { - return pv->getKind() == PersistentExpressionState::eKindClang; - } - - lldb::ExpressionVariableSP - CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) override; - - lldb::ExpressionVariableSP - CreatePersistentVariable (ExecutionContextScope *exe_scope, - const ConstString &name, - const CompilerType& compiler_type, - lldb::ByteOrder byte_order, - uint32_t addr_byte_size) override; - - //---------------------------------------------------------------------- - /// Return the next entry in the sequence of strings "$0", "$1", ... for - /// use naming persistent expression convenience variables. - /// - /// @return - /// A string that contains the next persistent variable name. - //---------------------------------------------------------------------- - ConstString - GetNextPersistentVariableName () override; - - void - RemovePersistentVariable (lldb::ExpressionVariableSP variable) override; - - void - RegisterPersistentDecl (const ConstString &name, - clang::NamedDecl *decl); - - clang::NamedDecl * - GetPersistentDecl (const ConstString &name); - - void - AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module) - { - m_hand_loaded_clang_modules.push_back(module); - } - - const ClangModulesDeclVendor::ModuleVector &GetHandLoadedClangModules() - { - return m_hand_loaded_clang_modules; - } - + ClangPersistentVariables(); + + ~ClangPersistentVariables() override = default; + + //------------------------------------------------------------------ + // llvm casting support + //------------------------------------------------------------------ + static bool classof(const PersistentExpressionState *pv) { + return pv->getKind() == PersistentExpressionState::eKindClang; + } + + lldb::ExpressionVariableSP + CreatePersistentVariable(const lldb::ValueObjectSP &valobj_sp) override; + + lldb::ExpressionVariableSP CreatePersistentVariable( + ExecutionContextScope *exe_scope, const ConstString &name, + const CompilerType &compiler_type, lldb::ByteOrder byte_order, + uint32_t addr_byte_size) override; + + //---------------------------------------------------------------------- + /// Return the next entry in the sequence of strings "$0", "$1", ... for + /// use naming persistent expression convenience variables. + /// + /// @return + /// A string that contains the next persistent variable name. + //---------------------------------------------------------------------- + ConstString GetNextPersistentVariableName() override; + + void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override; + + void RegisterPersistentDecl(const ConstString &name, clang::NamedDecl *decl); + + clang::NamedDecl *GetPersistentDecl(const ConstString &name); + + void AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module) { + m_hand_loaded_clang_modules.push_back(module); + } + + const ClangModulesDeclVendor::ModuleVector &GetHandLoadedClangModules() { + return m_hand_loaded_clang_modules; + } + private: - uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName(). - - typedef llvm::DenseMap<const char *, clang::NamedDecl *> PersistentDeclMap; - PersistentDeclMap m_persistent_decls; ///< Persistent entities declared by the user. - - ClangModulesDeclVendor::ModuleVector m_hand_loaded_clang_modules; ///< These are Clang modules we hand-loaded; these are the highest- - ///< priority source for macros. + uint32_t m_next_persistent_variable_id; ///< The counter used by + ///GetNextResultName(). + + typedef llvm::DenseMap<const char *, clang::NamedDecl *> PersistentDeclMap; + PersistentDeclMap + m_persistent_decls; ///< Persistent entities declared by the user. + + ClangModulesDeclVendor::ModuleVector + m_hand_loaded_clang_modules; ///< These are Clang modules we hand-loaded; + ///these are the highest- + ///< priority source for macros. }; } // namespace lldb_private diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 52d49aecec9..c456e411b19 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -9,21 +9,21 @@ #include <stdio.h> #if HAVE_SYS_TYPES_H -# include <sys/types.h> +#include <sys/types.h> #endif #include <cstdlib> -#include <string> #include <map> +#include <string> #include "ClangUserExpression.h" #include "ASTResultSynthesizer.h" +#include "ClangDiagnostic.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionParser.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" -#include "ClangDiagnostic.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Debugger.h" @@ -39,11 +39,11 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Type.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -57,676 +57,633 @@ using namespace lldb_private; -ClangUserExpression::ClangUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, - lldb::LanguageType language, ResultType desired_type, - const EvaluateExpressionOptions &options) - : LLVMUserExpression(exe_scope, expr, expr_prefix, language, desired_type, options), - m_type_system_helper(*m_target_wp.lock().get(), options.GetExecutionPolicy() == eExecutionPolicyTopLevel) -{ - switch (m_language) - { - case lldb::eLanguageTypeC_plus_plus: - m_allow_cxx = true; - break; - case lldb::eLanguageTypeObjC: - m_allow_objc = true; - break; - case lldb::eLanguageTypeObjC_plus_plus: - default: - m_allow_cxx = true; - m_allow_objc = true; - break; - } +ClangUserExpression::ClangUserExpression( + ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, + lldb::LanguageType language, ResultType desired_type, + const EvaluateExpressionOptions &options) + : LLVMUserExpression(exe_scope, expr, expr_prefix, language, desired_type, + options), + m_type_system_helper(*m_target_wp.lock().get(), + options.GetExecutionPolicy() == + eExecutionPolicyTopLevel) { + switch (m_language) { + case lldb::eLanguageTypeC_plus_plus: + m_allow_cxx = true; + break; + case lldb::eLanguageTypeObjC: + m_allow_objc = true; + break; + case lldb::eLanguageTypeObjC_plus_plus: + default: + m_allow_cxx = true; + m_allow_objc = true; + break; + } } -ClangUserExpression::~ClangUserExpression () -{ -} +ClangUserExpression::~ClangUserExpression() {} + +void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); -void -ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (log) + log->Printf("ClangUserExpression::ScanContext()"); + m_target = exe_ctx.GetTargetPtr(); + + if (!(m_allow_cxx || m_allow_objc)) { if (log) - log->Printf("ClangUserExpression::ScanContext()"); + log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C"); + return; + } - m_target = exe_ctx.GetTargetPtr(); + StackFrame *frame = exe_ctx.GetFramePtr(); + if (frame == NULL) { + if (log) + log->Printf(" [CUE::SC] Null stack frame"); + return; + } - if (!(m_allow_cxx || m_allow_objc)) - { - if (log) - log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C"); - return; - } + SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | + lldb::eSymbolContextBlock); - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame == NULL) - { - if (log) - log->Printf(" [CUE::SC] Null stack frame"); - return; - } + if (!sym_ctx.function) { + if (log) + log->Printf(" [CUE::SC] Null function"); + return; + } - SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); - if (!sym_ctx.function) - { - if (log) - log->Printf(" [CUE::SC] Null function"); - return; - } + if (!function_block) { + if (log) + log->Printf(" [CUE::SC] Null function block"); + return; + } - // Find the block that defines the function represented by "sym_ctx" - Block *function_block = sym_ctx.GetFunctionBlock(); + CompilerDeclContext decl_context = function_block->GetDeclContext(); - if (!function_block) - { - if (log) - log->Printf(" [CUE::SC] Null function block"); - return; - } + if (!decl_context) { + if (log) + log->Printf(" [CUE::SC] Null decl context"); + return; + } + + if (clang::CXXMethodDecl *method_decl = + ClangASTContext::DeclContextGetAsCXXMethodDecl(decl_context)) { + if (m_allow_cxx && method_decl->isInstance()) { + if (m_enforce_valid_object) { + lldb::VariableListSP variable_list_sp( + function_block->GetBlockVariableList(true)); + + const char *thisErrorString = "Stopped in a C++ method, but 'this' " + "isn't available; pretending we are in a " + "generic context"; + + if (!variable_list_sp) { + err.SetErrorString(thisErrorString); + return; + } - CompilerDeclContext decl_context = function_block->GetDeclContext(); + lldb::VariableSP this_var_sp( + variable_list_sp->FindVariable(ConstString("this"))); + + if (!this_var_sp || !this_var_sp->IsInScope(frame) || + !this_var_sp->LocationIsValidForFrame(frame)) { + err.SetErrorString(thisErrorString); + return; + } + } - if (!decl_context) - { - if (log) - log->Printf(" [CUE::SC] Null decl context"); - return; + m_in_cplusplus_method = true; + m_needs_object_ptr = true; } + } else if (clang::ObjCMethodDecl *method_decl = + ClangASTContext::DeclContextGetAsObjCMethodDecl( + decl_context)) { + if (m_allow_objc) { + if (m_enforce_valid_object) { + lldb::VariableListSP variable_list_sp( + function_block->GetBlockVariableList(true)); + + const char *selfErrorString = "Stopped in an Objective-C method, but " + "'self' isn't available; pretending we " + "are in a generic context"; + + if (!variable_list_sp) { + err.SetErrorString(selfErrorString); + return; + } - if (clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(decl_context)) - { - if (m_allow_cxx && method_decl->isInstance()) - { - if (m_enforce_valid_object) - { - lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - - const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context"; - - if (!variable_list_sp) - { - err.SetErrorString(thisErrorString); - return; - } - - lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); - - if (!this_var_sp || - !this_var_sp->IsInScope(frame) || - !this_var_sp->LocationIsValidForFrame (frame)) - { - err.SetErrorString(thisErrorString); - return; - } - } - - m_in_cplusplus_method = true; - m_needs_object_ptr = true; + lldb::VariableSP self_variable_sp = + variable_list_sp->FindVariable(ConstString("self")); + + if (!self_variable_sp || !self_variable_sp->IsInScope(frame) || + !self_variable_sp->LocationIsValidForFrame(frame)) { + err.SetErrorString(selfErrorString); + return; } + } + + m_in_objectivec_method = true; + m_needs_object_ptr = true; + + if (!method_decl->isInstanceMethod()) + m_in_static_method = true; } - else if (clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(decl_context)) - { - if (m_allow_objc) - { - if (m_enforce_valid_object) - { - lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - - const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context"; - - if (!variable_list_sp) - { - err.SetErrorString(selfErrorString); - return; - } - - lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); - - if (!self_variable_sp || - !self_variable_sp->IsInScope(frame) || - !self_variable_sp->LocationIsValidForFrame (frame)) - { - err.SetErrorString(selfErrorString); - return; - } - } + } else if (clang::FunctionDecl *function_decl = + ClangASTContext::DeclContextGetAsFunctionDecl(decl_context)) { + // We might also have a function that said in the debug information that it + // captured an + // object pointer. The best way to deal with getting to the ivars at + // present is by pretending + // that this is a method of a class in whatever runtime the debug info says + // the object pointer + // belongs to. Do that here. + + ClangASTMetadata *metadata = + ClangASTContext::DeclContextGetMetaData(decl_context, function_decl); + if (metadata && metadata->HasObjectPtr()) { + lldb::LanguageType language = metadata->GetObjectPtrLanguage(); + if (language == lldb::eLanguageTypeC_plus_plus) { + if (m_enforce_valid_object) { + lldb::VariableListSP variable_list_sp( + function_block->GetBlockVariableList(true)); + + const char *thisErrorString = "Stopped in a context claiming to " + "capture a C++ object pointer, but " + "'this' isn't available; pretending we " + "are in a generic context"; + + if (!variable_list_sp) { + err.SetErrorString(thisErrorString); + return; + } + + lldb::VariableSP this_var_sp( + variable_list_sp->FindVariable(ConstString("this"))); + + if (!this_var_sp || !this_var_sp->IsInScope(frame) || + !this_var_sp->LocationIsValidForFrame(frame)) { + err.SetErrorString(thisErrorString); + return; + } + } + m_in_cplusplus_method = true; + m_needs_object_ptr = true; + } else if (language == lldb::eLanguageTypeObjC) { + if (m_enforce_valid_object) { + lldb::VariableListSP variable_list_sp( + function_block->GetBlockVariableList(true)); + + const char *selfErrorString = + "Stopped in a context claiming to capture an Objective-C object " + "pointer, but 'self' isn't available; pretending we are in a " + "generic context"; + + if (!variable_list_sp) { + err.SetErrorString(selfErrorString); + return; + } + + lldb::VariableSP self_variable_sp = + variable_list_sp->FindVariable(ConstString("self")); + + if (!self_variable_sp || !self_variable_sp->IsInScope(frame) || + !self_variable_sp->LocationIsValidForFrame(frame)) { + err.SetErrorString(selfErrorString); + return; + } + + Type *self_type = self_variable_sp->GetType(); + + if (!self_type) { + err.SetErrorString(selfErrorString); + return; + } + + CompilerType self_clang_type = self_type->GetForwardCompilerType(); + + if (!self_clang_type) { + err.SetErrorString(selfErrorString); + return; + } + + if (ClangASTContext::IsObjCClassType(self_clang_type)) { + return; + } else if (ClangASTContext::IsObjCObjectPointerType( + self_clang_type)) { m_in_objectivec_method = true; m_needs_object_ptr = true; - - if (!method_decl->isInstanceMethod()) - m_in_static_method = true; - } - } - else if (clang::FunctionDecl *function_decl = ClangASTContext::DeclContextGetAsFunctionDecl(decl_context)) - { - // We might also have a function that said in the debug information that it captured an - // object pointer. The best way to deal with getting to the ivars at present is by pretending - // that this is a method of a class in whatever runtime the debug info says the object pointer - // belongs to. Do that here. - - ClangASTMetadata *metadata = ClangASTContext::DeclContextGetMetaData (decl_context, function_decl); - if (metadata && metadata->HasObjectPtr()) - { - lldb::LanguageType language = metadata->GetObjectPtrLanguage(); - if (language == lldb::eLanguageTypeC_plus_plus) - { - if (m_enforce_valid_object) - { - lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - - const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context"; - - if (!variable_list_sp) - { - err.SetErrorString(thisErrorString); - return; - } - - lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); - - if (!this_var_sp || - !this_var_sp->IsInScope(frame) || - !this_var_sp->LocationIsValidForFrame (frame)) - { - err.SetErrorString(thisErrorString); - return; - } - } - - m_in_cplusplus_method = true; - m_needs_object_ptr = true; - } - else if (language == lldb::eLanguageTypeObjC) - { - if (m_enforce_valid_object) - { - lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - - const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context"; - - if (!variable_list_sp) - { - err.SetErrorString(selfErrorString); - return; - } - - lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); - - if (!self_variable_sp || - !self_variable_sp->IsInScope(frame) || - !self_variable_sp->LocationIsValidForFrame (frame)) - { - err.SetErrorString(selfErrorString); - return; - } - - Type *self_type = self_variable_sp->GetType(); - - if (!self_type) - { - err.SetErrorString(selfErrorString); - return; - } - - CompilerType self_clang_type = self_type->GetForwardCompilerType (); - - if (!self_clang_type) - { - err.SetErrorString(selfErrorString); - return; - } - - if (ClangASTContext::IsObjCClassType(self_clang_type)) - { - return; - } - else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type)) - { - m_in_objectivec_method = true; - m_needs_object_ptr = true; - } - else - { - err.SetErrorString(selfErrorString); - return; - } - } - else - { - m_in_objectivec_method = true; - m_needs_object_ptr = true; - } - } + } else { + err.SetErrorString(selfErrorString); + return; + } + } else { + m_in_objectivec_method = true; + m_needs_object_ptr = true; } + } } + } } // This is a really nasty hack, meant to fix Objective-C expressions of the form // (int)[myArray count]. Right now, because the type information for count is // not available, [myArray count] returns id, which can't be directly cast to // int without causing a clang error. -static void -ApplyObjcCastHack(std::string &expr) -{ +static void ApplyObjcCastHack(std::string &expr) { #define OBJC_CAST_HACK_FROM "(int)[" -#define OBJC_CAST_HACK_TO "(int)(long long)[" +#define OBJC_CAST_HACK_TO "(int)(long long)[" - size_t from_offset; + size_t from_offset; - while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos) - expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO); + while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos) + expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, + OBJC_CAST_HACK_TO); #undef OBJC_CAST_HACK_TO #undef OBJC_CAST_HACK_FROM } -bool -ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, - bool generate_debug_info) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - Error err; - - InstallContext(exe_ctx); - - if (Target *target = exe_ctx.GetTargetPtr()) - { - if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)) - { - m_result_delegate.RegisterPersistentState(persistent_state); - } - else - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't start parsing (no persistent data)"); - return false; - } +bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, + bool generate_debug_info) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + Error err; + + InstallContext(exe_ctx); + + if (Target *target = exe_ctx.GetTargetPtr()) { + if (PersistentExpressionState *persistent_state = + target->GetPersistentExpressionStateForLanguage( + lldb::eLanguageTypeC)) { + m_result_delegate.RegisterPersistentState(persistent_state); + } else { + diagnostic_manager.PutCString( + eDiagnosticSeverityError, + "couldn't start parsing (no persistent data)"); + return false; } - else - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, "error: couldn't start parsing (no target)"); - return false; + } else { + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "error: couldn't start parsing (no target)"); + return false; + } + + ScanContext(exe_ctx, err); + + if (!err.Success()) { + diagnostic_manager.PutCString(eDiagnosticSeverityWarning, err.AsCString()); + } + + //////////////////////////////////// + // Generate the expression + // + + ApplyObjcCastHack(m_expr_text); + // ApplyUnicharHack(m_expr_text); + + std::string prefix = m_expr_prefix; + + if (ClangModulesDeclVendor *decl_vendor = + m_target->GetClangModulesDeclVendor()) { + const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = + llvm::cast<ClangPersistentVariables>( + m_target->GetPersistentExpressionStateForLanguage( + lldb::eLanguageTypeC)) + ->GetHandLoadedClangModules(); + ClangModulesDeclVendor::ModuleVector modules_for_macros; + + for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) { + modules_for_macros.push_back(module); } - ScanContext(exe_ctx, err); + if (m_target->GetEnableAutoImportClangModules()) { + if (StackFrame *frame = exe_ctx.GetFramePtr()) { + if (Block *block = frame->GetFrameBlock()) { + SymbolContext sc; - if (!err.Success()) - { - diagnostic_manager.PutCString(eDiagnosticSeverityWarning, err.AsCString()); - } + block->CalculateSymbolContext(&sc); - //////////////////////////////////// - // Generate the expression - // - - ApplyObjcCastHack(m_expr_text); - //ApplyUnicharHack(m_expr_text); - - std::string prefix = m_expr_prefix; - - if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor()) - { - const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast<ClangPersistentVariables>(m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->GetHandLoadedClangModules(); - ClangModulesDeclVendor::ModuleVector modules_for_macros; - - for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) - { - modules_for_macros.push_back(module); - } + if (sc.comp_unit) { + StreamString error_stream; - if (m_target->GetEnableAutoImportClangModules()) - { - if (StackFrame *frame = exe_ctx.GetFramePtr()) - { - if (Block *block = frame->GetFrameBlock()) - { - SymbolContext sc; - - block->CalculateSymbolContext(&sc); - - if (sc.comp_unit) - { - StreamString error_stream; - - decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream); - } - } - } + decl_vendor->AddModulesForCompileUnit( + *sc.comp_unit, modules_for_macros, error_stream); + } } + } } + } - lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; + lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; - if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) - { - m_transformed_text = m_expr_text; - } + if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { + m_transformed_text = m_expr_text; + } else { + std::unique_ptr<ExpressionSourceCode> source_code( + ExpressionSourceCode::CreateWrapped(prefix.c_str(), + m_expr_text.c_str())); + + if (m_in_cplusplus_method) + lang_type = lldb::eLanguageTypeC_plus_plus; + else if (m_in_objectivec_method) + lang_type = lldb::eLanguageTypeObjC; else - { - std::unique_ptr<ExpressionSourceCode> source_code( - ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str())); - - if (m_in_cplusplus_method) - lang_type = lldb::eLanguageTypeC_plus_plus; - else if (m_in_objectivec_method) - lang_type = lldb::eLanguageTypeObjC; - else - lang_type = lldb::eLanguageTypeC; - - if (!source_code->GetText(m_transformed_text, lang_type, m_in_static_method, exe_ctx)) - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't construct expression body"); - return false; - } + lang_type = lldb::eLanguageTypeC; + + if (!source_code->GetText(m_transformed_text, lang_type, m_in_static_method, + exe_ctx)) { + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "couldn't construct expression body"); + return false; } + } - if (log) - log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); + if (log) + log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); - //////////////////////////////////// - // Set up the target and compiler - // + //////////////////////////////////// + // Set up the target and compiler + // - Target *target = exe_ctx.GetTargetPtr(); + Target *target = exe_ctx.GetTargetPtr(); - if (!target) - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target"); - return false; - } + if (!target) { + diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target"); + return false; + } - ////////////////////////// - // Parse the expression - // + ////////////////////////// + // Parse the expression + // - m_materializer_ap.reset(new Materializer()); + m_materializer_ap.reset(new Materializer()); - ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory); + ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory); - class OnExit - { - public: - typedef std::function <void (void)> Callback; + class OnExit { + public: + typedef std::function<void(void)> Callback; - OnExit (Callback const &callback) : - m_callback(callback) - { - } + OnExit(Callback const &callback) : m_callback(callback) {} - ~OnExit () - { - m_callback(); - } - private: - Callback m_callback; - }; + ~OnExit() { m_callback(); } - OnExit on_exit([this]() { ResetDeclMap(); }); + private: + Callback m_callback; + }; - if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, - "current process state is unsuitable for expression parsing"); + OnExit on_exit([this]() { ResetDeclMap(); }); - ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. + if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) { + diagnostic_manager.PutCString( + eDiagnosticSeverityError, + "current process state is unsuitable for expression parsing"); - return false; - } + ResetDeclMap(); // We are being careful here in the case of breakpoint + // conditions. - if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) - { - DeclMap()->SetLookupsEnabled(true); - } + return false; + } - Process *process = exe_ctx.GetProcessPtr(); - ExecutionContextScope *exe_scope = process; - - if (!exe_scope) - exe_scope = exe_ctx.GetTargetPtr(); - - // We use a shared pointer here so we can use the original parser - if it succeeds - // or the rewrite parser we might make if it fails. But the parser_sp will never be empty. - - ClangExpressionParser parser(exe_scope, *this, generate_debug_info); - - unsigned num_errors = parser.Parse(diagnostic_manager); - - // Check here for FixItHints. If there are any try to apply the fixits and set the fixed text in m_fixed_text - // before returning an error. - if (num_errors) - { - if (diagnostic_manager.HasFixIts()) - { - if (parser.RewriteExpression(diagnostic_manager)) - { - size_t fixed_start; - size_t fixed_end; - const std::string &fixed_expression = diagnostic_manager.GetFixedExpression(); - if (ExpressionSourceCode::GetOriginalBodyBounds(fixed_expression, lang_type, fixed_start, fixed_end)) - m_fixed_text = fixed_expression.substr(fixed_start, fixed_end - fixed_start); - } - } + if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { + DeclMap()->SetLookupsEnabled(true); + } - ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. + Process *process = exe_ctx.GetProcessPtr(); + ExecutionContextScope *exe_scope = process; - return false; - } + if (!exe_scope) + exe_scope = exe_ctx.GetTargetPtr(); - ////////////////////////////////////////////////////////////////////////////////////////// - // Prepare the output of the parser for execution, evaluating it statically if possible - // - - { - Error jit_error = parser.PrepareForExecution(m_jit_start_addr, - m_jit_end_addr, - m_execution_unit_sp, - exe_ctx, - m_can_interpret, - execution_policy); - - if (!jit_error.Success()) - { - const char *error_cstr = jit_error.AsCString(); - if (error_cstr && error_cstr[0]) - diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr); - else - diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); - return false; - } + // We use a shared pointer here so we can use the original parser - if it + // succeeds + // or the rewrite parser we might make if it fails. But the parser_sp will + // never be empty. + + ClangExpressionParser parser(exe_scope, *this, generate_debug_info); + + unsigned num_errors = parser.Parse(diagnostic_manager); + + // Check here for FixItHints. If there are any try to apply the fixits and + // set the fixed text in m_fixed_text + // before returning an error. + if (num_errors) { + if (diagnostic_manager.HasFixIts()) { + if (parser.RewriteExpression(diagnostic_manager)) { + size_t fixed_start; + size_t fixed_end; + const std::string &fixed_expression = + diagnostic_manager.GetFixedExpression(); + if (ExpressionSourceCode::GetOriginalBodyBounds( + fixed_expression, lang_type, fixed_start, fixed_end)) + m_fixed_text = + fixed_expression.substr(fixed_start, fixed_end - fixed_start); + } } - if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) - { - Error static_init_error = parser.RunStaticInitializers(m_execution_unit_sp, exe_ctx); - - if (!static_init_error.Success()) - { - const char *error_cstr = static_init_error.AsCString(); - if (error_cstr && error_cstr[0]) - diagnostic_manager.Printf(eDiagnosticSeverityError, "couldn't run static initializers: %s\n", - error_cstr); - else - diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't run static initializers\n"); - return false; - } + ResetDeclMap(); // We are being careful here in the case of breakpoint + // conditions. + + return false; + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // Prepare the output of the parser for execution, evaluating it statically if + // possible + // + + { + Error jit_error = parser.PrepareForExecution( + m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx, + m_can_interpret, execution_policy); + + if (!jit_error.Success()) { + const char *error_cstr = jit_error.AsCString(); + if (error_cstr && error_cstr[0]) + diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr); + else + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "expression can't be interpreted or run"); + return false; + } + } + + if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) { + Error static_init_error = + parser.RunStaticInitializers(m_execution_unit_sp, exe_ctx); + + if (!static_init_error.Success()) { + const char *error_cstr = static_init_error.AsCString(); + if (error_cstr && error_cstr[0]) + diagnostic_manager.Printf(eDiagnosticSeverityError, + "couldn't run static initializers: %s\n", + error_cstr); + else + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "couldn't run static initializers\n"); + return false; } + } - if (m_execution_unit_sp) - { - bool register_execution_unit = false; + if (m_execution_unit_sp) { + bool register_execution_unit = false; - if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) - { - register_execution_unit = true; - } - - // If there is more than one external function in the execution - // unit, it needs to keep living even if it's not top level, because - // the result could refer to that function. - - if (m_execution_unit_sp->GetJittedFunctions().size() > 1) - { - register_execution_unit = true; - } + if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { + register_execution_unit = true; + } - if (register_execution_unit) - { - llvm::cast<PersistentExpressionState>( - exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(m_language)) - ->RegisterExecutionUnit(m_execution_unit_sp); - } + // If there is more than one external function in the execution + // unit, it needs to keep living even if it's not top level, because + // the result could refer to that function. + + if (m_execution_unit_sp->GetJittedFunctions().size() > 1) { + register_execution_unit = true; } - if (generate_debug_info) - { - lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule()); - - if (jit_module_sp) - { - ConstString const_func_name(FunctionName()); - FileSpec jit_file; - jit_file.GetFilename() = const_func_name; - jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); - m_jit_module_wp = jit_module_sp; - target->GetImages().Append(jit_module_sp); - } + if (register_execution_unit) { + llvm::cast<PersistentExpressionState>( + exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage( + m_language)) + ->RegisterExecutionUnit(m_execution_unit_sp); + } + } + + if (generate_debug_info) { + lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule()); + + if (jit_module_sp) { + ConstString const_func_name(FunctionName()); + FileSpec jit_file; + jit_file.GetFilename() = const_func_name; + jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString()); + m_jit_module_wp = jit_module_sp; + target->GetImages().Append(jit_module_sp); } + } - ResetDeclMap(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any - // ClangASTImporter::Minions. + ResetDeclMap(); // Make this go away since we don't need any of its state + // after parsing. This also gets rid of any + // ClangASTImporter::Minions. - if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) - m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); - return true; + if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) + m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); + return true; } -bool -ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, - lldb::addr_t struct_address, DiagnosticManager &diagnostic_manager) -{ - lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS; - lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; - - if (m_needs_object_ptr) - { - lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); - if (!frame_sp) - return true; - - ConstString object_name; - - if (m_in_cplusplus_method) - { - object_name.SetCString("this"); - } - else if (m_in_objectivec_method) - { - object_name.SetCString("self"); - } - else - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, "need object pointer but don't know the language"); - return false; - } +bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, + std::vector<lldb::addr_t> &args, + lldb::addr_t struct_address, + DiagnosticManager &diagnostic_manager) { + lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS; + lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; + + if (m_needs_object_ptr) { + lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); + if (!frame_sp) + return true; + + ConstString object_name; + + if (m_in_cplusplus_method) { + object_name.SetCString("this"); + } else if (m_in_objectivec_method) { + object_name.SetCString("self"); + } else { + diagnostic_manager.PutCString( + eDiagnosticSeverityError, + "need object pointer but don't know the language"); + return false; + } - Error object_ptr_error; + Error object_ptr_error; - object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error); + object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error); - if (!object_ptr_error.Success()) - { - exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf("warning: `%s' is not accessible (subsituting 0)\n", object_name.AsCString()); - object_ptr = 0; - } + if (!object_ptr_error.Success()) { + exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf( + "warning: `%s' is not accessible (subsituting 0)\n", + object_name.AsCString()); + object_ptr = 0; + } - if (m_in_objectivec_method) - { - ConstString cmd_name("_cmd"); + if (m_in_objectivec_method) { + ConstString cmd_name("_cmd"); - cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error); + cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error); - if (!object_ptr_error.Success()) - { - diagnostic_manager.Printf(eDiagnosticSeverityWarning, - "couldn't get cmd pointer (substituting NULL): %s", - object_ptr_error.AsCString()); - cmd_ptr = 0; - } - } - - args.push_back(object_ptr); + if (!object_ptr_error.Success()) { + diagnostic_manager.Printf( + eDiagnosticSeverityWarning, + "couldn't get cmd pointer (substituting NULL): %s", + object_ptr_error.AsCString()); + cmd_ptr = 0; + } + } - if (m_in_objectivec_method) - args.push_back(cmd_ptr); + args.push_back(object_ptr); - args.push_back(struct_address); - } - else - { - args.push_back(struct_address); - } - return true; + if (m_in_objectivec_method) + args.push_back(cmd_ptr); + + args.push_back(struct_address); + } else { + args.push_back(struct_address); + } + return true; } -lldb::ExpressionVariableSP -ClangUserExpression::GetResultAfterDematerialization(ExecutionContextScope *exe_scope) -{ - return m_result_delegate.GetVariable(); +lldb::ExpressionVariableSP ClangUserExpression::GetResultAfterDematerialization( + ExecutionContextScope *exe_scope) { + return m_result_delegate.GetVariable(); } -void -ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &delegate, bool keep_result_in_memory) -{ - m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx)); +void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap( + ExecutionContext &exe_ctx, + Materializer::PersistentVariableDelegate &delegate, + bool keep_result_in_memory) { + m_expr_decl_map_up.reset( + new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx)); } clang::ASTConsumer * -ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(clang::ASTConsumer *passthrough) -{ - m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, m_top_level, m_target)); +ClangUserExpression::ClangUserExpressionHelper::ASTTransformer( + clang::ASTConsumer *passthrough) { + m_result_synthesizer_up.reset( + new ASTResultSynthesizer(passthrough, m_top_level, m_target)); - return m_result_synthesizer_up.get(); + return m_result_synthesizer_up.get(); } -void -ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() -{ - if (m_result_synthesizer_up.get()) - { - m_result_synthesizer_up->CommitPersistentDecls(); - } +void ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() { + if (m_result_synthesizer_up.get()) { + m_result_synthesizer_up->CommitPersistentDecls(); + } } -ClangUserExpression::ResultDelegate::ResultDelegate() -{ -} +ClangUserExpression::ResultDelegate::ResultDelegate() {} -ConstString -ClangUserExpression::ResultDelegate::GetName() -{ - return m_persistent_state->GetNextPersistentVariableName(); +ConstString ClangUserExpression::ResultDelegate::GetName() { + return m_persistent_state->GetNextPersistentVariableName(); } -void -ClangUserExpression::ResultDelegate::DidDematerialize(lldb::ExpressionVariableSP &variable) -{ - m_variable = variable; +void ClangUserExpression::ResultDelegate::DidDematerialize( + lldb::ExpressionVariableSP &variable) { + m_variable = variable; } -void -ClangUserExpression::ResultDelegate::RegisterPersistentState(PersistentExpressionState *persistent_state) -{ - m_persistent_state = persistent_state; +void ClangUserExpression::ResultDelegate::RegisterPersistentState( + PersistentExpressionState *persistent_state) { + m_persistent_state = persistent_state; } -lldb::ExpressionVariableSP & -ClangUserExpression::ResultDelegate::GetVariable() -{ - return m_variable; +lldb::ExpressionVariableSP &ClangUserExpression::ResultDelegate::GetVariable() { + return m_variable; } - diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index 6077588b024..1aea69fd45f 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -16,26 +16,26 @@ // Other libraries and framework includes // Project includes -#include "ASTStructExtractor.h" #include "ASTResultSynthesizer.h" +#include "ASTStructExtractor.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionHelper.h" #include "ClangExpressionVariable.h" #include "IRForTarget.h" -#include "lldb/lldb-forward.h" -#include "lldb/lldb-private.h" #include "lldb/Core/Address.h" #include "lldb/Core/ClangForward.h" #include "lldb/Expression/LLVMUserExpression.h" #include "lldb/Expression/Materializer.h" #include "lldb/Target/ExecutionContext.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" -namespace lldb_private -{ +namespace lldb_private { //---------------------------------------------------------------------- -/// @class ClangUserExpression ClangUserExpression.h "lldb/Expression/ClangUserExpression.h" +/// @class ClangUserExpression ClangUserExpression.h +/// "lldb/Expression/ClangUserExpression.h" /// @brief Encapsulates a single expression for use with Clang /// /// LLDB uses expressions for various purposes, notably to call functions @@ -43,172 +43,154 @@ namespace lldb_private /// the objects needed to parse and interpret or JIT an expression. It /// uses the Clang parser to produce LLVM IR from the expression. //---------------------------------------------------------------------- -class ClangUserExpression : public LLVMUserExpression -{ +class ClangUserExpression : public LLVMUserExpression { public: - enum { kDefaultTimeout = 500000u }; - - class ClangUserExpressionHelper : public ClangExpressionHelper - { - public: - ClangUserExpressionHelper(Target &target, bool top_level) : m_target(target), m_top_level(top_level) {} - - ~ClangUserExpressionHelper() override = default; - - //------------------------------------------------------------------ - /// Return the object that the parser should use when resolving external - /// values. May be NULL if everything should be self-contained. - //------------------------------------------------------------------ - ClangExpressionDeclMap * - DeclMap() override - { - return m_expr_decl_map_up.get(); - } - - void - ResetDeclMap() - { - m_expr_decl_map_up.reset(); - } - - void - ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory); - - //------------------------------------------------------------------ - /// Return the object that the parser should allow to access ASTs. - /// May be NULL if the ASTs do not need to be transformed. - /// - /// @param[in] passthrough - /// The ASTConsumer that the returned transformer should send - /// the ASTs to after transformation. - //------------------------------------------------------------------ - clang::ASTConsumer * - ASTTransformer(clang::ASTConsumer *passthrough) override; - - void - CommitPersistentDecls() override; - - private: - Target &m_target; - std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up; - std::unique_ptr<ASTStructExtractor> - m_struct_extractor_up; ///< The class that generates the argument struct layout. - std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer_up; - bool m_top_level; - }; + enum { kDefaultTimeout = 500000u }; + + class ClangUserExpressionHelper : public ClangExpressionHelper { + public: + ClangUserExpressionHelper(Target &target, bool top_level) + : m_target(target), m_top_level(top_level) {} + + ~ClangUserExpressionHelper() override = default; //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] expr - /// The expression to parse. - /// - /// @param[in] expr_prefix - /// If non-NULL, a C string containing translation-unit level - /// definitions to be included when the expression is parsed. - /// - /// @param[in] language - /// If not eLanguageTypeUnknown, a language to use when parsing - /// the expression. Currently restricted to those languages - /// supported by Clang. - /// - /// @param[in] desired_type - /// If not eResultTypeAny, the type to use for the expression - /// result. + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. //------------------------------------------------------------------ - ClangUserExpression (ExecutionContextScope &exe_scope, - const char *expr, - const char *expr_prefix, - lldb::LanguageType language, - ResultType desired_type, - const EvaluateExpressionOptions &options); + ClangExpressionDeclMap *DeclMap() override { + return m_expr_decl_map_up.get(); + } + + void ResetDeclMap() { m_expr_decl_map_up.reset(); } - ~ClangUserExpression() override; + void ResetDeclMap(ExecutionContext &exe_ctx, + Materializer::PersistentVariableDelegate &result_delegate, + bool keep_result_in_memory); //------------------------------------------------------------------ - /// Parse the expression - /// - /// @param[in] diagnostic_manager - /// A diagnostic manager to report parse errors and warnings to. + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. /// - /// @param[in] exe_ctx - /// The execution context to use when looking up entities that - /// are needed for parsing (locations of functions, types of - /// variables, persistent variables, etc.) - /// - /// @param[in] execution_policy - /// Determines whether interpretation is possible or mandatory. - /// - /// @param[in] keep_result_in_memory - /// True if the resulting persistent variable should reside in - /// target memory, if applicable. - /// - /// @return - /// True on success (no errors); false otherwise. + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. //------------------------------------------------------------------ - bool - Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, - bool generate_debug_info) override; - - ExpressionTypeSystemHelper * - GetTypeSystemHelper () override - { - return &m_type_system_helper; - } - - ClangExpressionDeclMap * - DeclMap () - { - return m_type_system_helper.DeclMap(); - } - - void - ResetDeclMap () - { - m_type_system_helper.ResetDeclMap(); - } - - void - ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory) - { - m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, keep_result_in_memory); - } + clang::ASTConsumer * + ASTTransformer(clang::ASTConsumer *passthrough) override; + + void CommitPersistentDecls() override; + + private: + Target &m_target; + std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up; + std::unique_ptr<ASTStructExtractor> m_struct_extractor_up; ///< The class + ///that generates + ///the argument + ///struct layout. + std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer_up; + bool m_top_level; + }; + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] expr + /// The expression to parse. + /// + /// @param[in] expr_prefix + /// If non-NULL, a C string containing translation-unit level + /// definitions to be included when the expression is parsed. + /// + /// @param[in] language + /// If not eLanguageTypeUnknown, a language to use when parsing + /// the expression. Currently restricted to those languages + /// supported by Clang. + /// + /// @param[in] desired_type + /// If not eResultTypeAny, the type to use for the expression + /// result. + //------------------------------------------------------------------ + ClangUserExpression(ExecutionContextScope &exe_scope, const char *expr, + const char *expr_prefix, lldb::LanguageType language, + ResultType desired_type, + const EvaluateExpressionOptions &options); + + ~ClangUserExpression() override; + + //------------------------------------------------------------------ + /// Parse the expression + /// + /// @param[in] diagnostic_manager + /// A diagnostic manager to report parse errors and warnings to. + /// + /// @param[in] exe_ctx + /// The execution context to use when looking up entities that + /// are needed for parsing (locations of functions, types of + /// variables, persistent variables, etc.) + /// + /// @param[in] execution_policy + /// Determines whether interpretation is possible or mandatory. + /// + /// @param[in] keep_result_in_memory + /// True if the resulting persistent variable should reside in + /// target memory, if applicable. + /// + /// @return + /// True on success (no errors); false otherwise. + //------------------------------------------------------------------ + bool Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, bool generate_debug_info) override; + + ExpressionTypeSystemHelper *GetTypeSystemHelper() override { + return &m_type_system_helper; + } + + ClangExpressionDeclMap *DeclMap() { return m_type_system_helper.DeclMap(); } + + void ResetDeclMap() { m_type_system_helper.ResetDeclMap(); } + + void ResetDeclMap(ExecutionContext &exe_ctx, + Materializer::PersistentVariableDelegate &result_delegate, + bool keep_result_in_memory) { + m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, + keep_result_in_memory); + } + + lldb::ExpressionVariableSP + GetResultAfterDematerialization(ExecutionContextScope *exe_scope) override; - lldb::ExpressionVariableSP - GetResultAfterDematerialization(ExecutionContextScope *exe_scope) override; - private: - //------------------------------------------------------------------ - /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment. - //------------------------------------------------------------------ + //------------------------------------------------------------------ + /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the + /// environment. + //------------------------------------------------------------------ + + void ScanContext(ExecutionContext &exe_ctx, + lldb_private::Error &err) override; + + bool AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, + lldb::addr_t struct_address, + DiagnosticManager &diagnostic_manager) override; + + ClangUserExpressionHelper m_type_system_helper; + + class ResultDelegate : public Materializer::PersistentVariableDelegate { + public: + ResultDelegate(); + ConstString GetName() override; + void DidDematerialize(lldb::ExpressionVariableSP &variable) override; + + void RegisterPersistentState(PersistentExpressionState *persistent_state); + lldb::ExpressionVariableSP &GetVariable(); + + private: + PersistentExpressionState *m_persistent_state; + lldb::ExpressionVariableSP m_variable; + }; - void - ScanContext (ExecutionContext &exe_ctx, - lldb_private::Error &err) override; - - bool - AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, lldb::addr_t struct_address, - DiagnosticManager &diagnostic_manager) override; - - ClangUserExpressionHelper m_type_system_helper; - - class ResultDelegate : public Materializer::PersistentVariableDelegate - { - public: - ResultDelegate(); - ConstString GetName() override; - void DidDematerialize(lldb::ExpressionVariableSP &variable) override; - - void RegisterPersistentState(PersistentExpressionState *persistent_state); - lldb::ExpressionVariableSP &GetVariable(); - - private: - PersistentExpressionState *m_persistent_state; - lldb::ExpressionVariableSP m_variable; - }; - - ResultDelegate m_result_delegate; + ResultDelegate m_result_delegate; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 727e4b3329b..d3af620145b 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -1,4 +1,5 @@ -//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===// +//===-- ClangUserExpression.cpp -------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -7,14 +8,14 @@ // //===----------------------------------------------------------------------===// +#include "ClangUtilityFunction.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionParser.h" -#include "ClangUtilityFunction.h" // C Includes #include <stdio.h> #if HAVE_SYS_TYPES_H -# include <sys/types.h> +#include <sys/types.h> #endif // C++ Includes @@ -41,16 +42,11 @@ using namespace lldb_private; /// @param[in] name /// The name of the function, as used in the text. //------------------------------------------------------------------ -ClangUtilityFunction::ClangUtilityFunction (ExecutionContextScope &exe_scope, - const char *text, - const char *name) : - UtilityFunction (exe_scope, text, name) -{ -} +ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope, + const char *text, const char *name) + : UtilityFunction(exe_scope, text, name) {} -ClangUtilityFunction::~ClangUtilityFunction () -{ -} +ClangUtilityFunction::~ClangUtilityFunction() {} //------------------------------------------------------------------ /// Install the utility function into a process @@ -64,94 +60,85 @@ ClangUtilityFunction::~ClangUtilityFunction () /// @return /// True on success (no errors); false otherwise. //------------------------------------------------------------------ -bool -ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) -{ - if (m_jit_start_addr != LLDB_INVALID_ADDRESS) - { - diagnostic_manager.PutCString(eDiagnosticSeverityWarning, "already installed"); - return false; - } +bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx) { + if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { + diagnostic_manager.PutCString(eDiagnosticSeverityWarning, + "already installed"); + return false; + } - //////////////////////////////////// - // Set up the target and compiler - // - - Target *target = exe_ctx.GetTargetPtr(); + //////////////////////////////////// + // Set up the target and compiler + // - if (!target) - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target"); - return false; - } + Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); + if (!target) { + diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target"); + return false; + } - if (!process) - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid process"); - return false; - } + Process *process = exe_ctx.GetProcessPtr(); - ////////////////////////// - // Parse the expression - // - - bool keep_result_in_memory = false; - - ResetDeclMap(exe_ctx, keep_result_in_memory); - - if (!DeclMap()->WillParse(exe_ctx, NULL)) - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, - "current process state is unsuitable for expression parsing"); - return false; - } + if (!process) { + diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid process"); + return false; + } - const bool generate_debug_info = true; - ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info); + ////////////////////////// + // Parse the expression + // - unsigned num_errors = parser.Parse(diagnostic_manager); + bool keep_result_in_memory = false; - if (num_errors) - { - ResetDeclMap(); + ResetDeclMap(exe_ctx, keep_result_in_memory); - return false; - } - - ////////////////////////////////// - // JIT the output of the parser - // - - bool can_interpret = false; // should stay that way - - Error jit_error = parser.PrepareForExecution (m_jit_start_addr, - m_jit_end_addr, - m_execution_unit_sp, - exe_ctx, - can_interpret, - eExecutionPolicyAlways); - - if (m_jit_start_addr != LLDB_INVALID_ADDRESS) - { - m_jit_process_wp = process->shared_from_this(); - if (parser.GetGenerateDebugInfo()) - { - lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); - - if (jit_module_sp) - { - ConstString const_func_name(FunctionName()); - FileSpec jit_file; - jit_file.GetFilename() = const_func_name; - jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); - m_jit_module_wp = jit_module_sp; - target->GetImages().Append(jit_module_sp); - } - } + if (!DeclMap()->WillParse(exe_ctx, NULL)) { + diagnostic_manager.PutCString( + eDiagnosticSeverityError, + "current process state is unsuitable for expression parsing"); + return false; + } + + const bool generate_debug_info = true; + ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, + generate_debug_info); + + unsigned num_errors = parser.Parse(diagnostic_manager); + + if (num_errors) { + ResetDeclMap(); + + return false; + } + + ////////////////////////////////// + // JIT the output of the parser + // + + bool can_interpret = false; // should stay that way + + Error jit_error = parser.PrepareForExecution( + m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx, + can_interpret, eExecutionPolicyAlways); + + if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { + m_jit_process_wp = process->shared_from_this(); + if (parser.GetGenerateDebugInfo()) { + lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule()); + + if (jit_module_sp) { + ConstString const_func_name(FunctionName()); + FileSpec jit_file; + jit_file.GetFilename() = const_func_name; + jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString()); + m_jit_module_wp = jit_module_sp; + target->GetImages().Append(jit_module_sp); + } } - + } + #if 0 // jingham: look here StreamFile logfile ("/tmp/exprs.txt", "a"); @@ -161,31 +148,26 @@ ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, ExecutionCo m_function_text.c_str()); #endif - DeclMap()->DidParse(); - - ResetDeclMap(); - - if (jit_error.Success()) - { - return true; - } - else - { - const char *error_cstr = jit_error.AsCString(); - if (error_cstr && error_cstr[0]) - { - diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr); - } - else - { - diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); - } - return false; + DeclMap()->DidParse(); + + ResetDeclMap(); + + if (jit_error.Success()) { + return true; + } else { + const char *error_cstr = jit_error.AsCString(); + if (error_cstr && error_cstr[0]) { + diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr); + } else { + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "expression can't be interpreted or run"); } + return false; + } } -void -ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory) -{ - m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx)); +void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap( + ExecutionContext &exe_ctx, bool keep_result_in_memory) { + m_expr_decl_map_up.reset( + new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx)); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h index d4ed37eee04..80577199b81 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -12,24 +12,24 @@ // C Includes // C++ Includes -#include <string> #include <map> +#include <string> #include <vector> // Other libraries and framework includes // Project includes #include "ClangExpressionHelper.h" -#include "lldb/lldb-forward.h" -#include "lldb/lldb-private.h" #include "lldb/Core/ClangForward.h" #include "lldb/Expression/UtilityFunction.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" -namespace lldb_private -{ +namespace lldb_private { //---------------------------------------------------------------------- -/// @class ClangUtilityFunction ClangUtilityFunction.h "lldb/Expression/ClangUtilityFunction.h" +/// @class ClangUtilityFunction ClangUtilityFunction.h +/// "lldb/Expression/ClangUtilityFunction.h" /// @brief Encapsulates a single expression for use with Clang /// /// LLDB uses expressions for various purposes, notably to call functions @@ -39,97 +39,75 @@ namespace lldb_private /// simply provide a way to push a function into the target for the debugger to /// call later on. //---------------------------------------------------------------------- -class ClangUtilityFunction : public UtilityFunction -{ +class ClangUtilityFunction : public UtilityFunction { public: - class ClangUtilityFunctionHelper : public ClangExpressionHelper - { - public: - ClangUtilityFunctionHelper () - { - } - - ~ClangUtilityFunctionHelper() override {} - - //------------------------------------------------------------------ - /// Return the object that the parser should use when resolving external - /// values. May be NULL if everything should be self-contained. - //------------------------------------------------------------------ - ClangExpressionDeclMap * - DeclMap() override - { - return m_expr_decl_map_up.get(); - } - - void - ResetDeclMap() - { - m_expr_decl_map_up.reset(); - } - - void - ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory); - - //------------------------------------------------------------------ - /// Return the object that the parser should allow to access ASTs. - /// May be NULL if the ASTs do not need to be transformed. - /// - /// @param[in] passthrough - /// The ASTConsumer that the returned transformer should send - /// the ASTs to after transformation. - //------------------------------------------------------------------ - clang::ASTConsumer * - ASTTransformer(clang::ASTConsumer *passthrough) override - { - return nullptr; - } - private: - std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up; - }; + class ClangUtilityFunctionHelper : public ClangExpressionHelper { + public: + ClangUtilityFunctionHelper() {} + + ~ClangUtilityFunctionHelper() override {} + //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] text - /// The text of the function. Must be a full translation unit. - /// - /// @param[in] name - /// The name of the function, as used in the text. + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. //------------------------------------------------------------------ - ClangUtilityFunction (ExecutionContextScope &exe_scope, - const char *text, - const char *name); - - ~ClangUtilityFunction() override; - - ExpressionTypeSystemHelper * - GetTypeSystemHelper () override - { - return &m_type_system_helper; + ClangExpressionDeclMap *DeclMap() override { + return m_expr_decl_map_up.get(); } - ClangExpressionDeclMap * - DeclMap() - { - return m_type_system_helper.DeclMap(); - } + void ResetDeclMap() { m_expr_decl_map_up.reset(); } - void - ResetDeclMap () - { - m_type_system_helper.ResetDeclMap(); - } - - void - ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory) - { - m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory); + void ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory); + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + clang::ASTConsumer * + ASTTransformer(clang::ASTConsumer *passthrough) override { + return nullptr; } - bool - Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) override; + private: + std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up; + }; + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] text + /// The text of the function. Must be a full translation unit. + /// + /// @param[in] name + /// The name of the function, as used in the text. + //------------------------------------------------------------------ + ClangUtilityFunction(ExecutionContextScope &exe_scope, const char *text, + const char *name); + + ~ClangUtilityFunction() override; + + ExpressionTypeSystemHelper *GetTypeSystemHelper() override { + return &m_type_system_helper; + } + + ClangExpressionDeclMap *DeclMap() { return m_type_system_helper.DeclMap(); } + + void ResetDeclMap() { m_type_system_helper.ResetDeclMap(); } + + void ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory) { + m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory); + } + + bool Install(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx) override; private: - ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression. + ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when + ///parsing and materializing + ///the expression. }; } // namespace lldb_private diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index 30e00ff6c72..db3f1589fa5 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -11,17 +11,17 @@ #include "ClangExpressionDeclMap.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Module.h" #include "llvm/IR/LegacyPassManager.h" -#include "llvm/Transforms/IPO.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/Module.h" #include "llvm/IR/ValueSymbolTable.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/IPO.h" #include "clang/AST/ASTContext.h" @@ -44,2116 +44,2047 @@ using namespace llvm; static char ID; -IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) : - m_maker(maker), - m_values() -{ -} +IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) + : m_maker(maker), m_values() {} -IRForTarget::FunctionValueCache::~FunctionValueCache() -{ -} +IRForTarget::FunctionValueCache::~FunctionValueCache() {} llvm::Value * -IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) -{ - if (!m_values.count(function)) - { - llvm::Value *ret = m_maker(function); - m_values[function] = ret; - return ret; - } - return m_values[function]; +IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) { + if (!m_values.count(function)) { + llvm::Value *ret = m_maker(function); + m_values[function] = ret; + return ret; + } + return m_values[function]; } -static llvm::Value * -FindEntryInstruction (llvm::Function *function) -{ - if (function->empty()) - return NULL; +static llvm::Value *FindEntryInstruction(llvm::Function *function) { + if (function->empty()) + return NULL; - return function->getEntryBlock().getFirstNonPHIOrDbg(); + return function->getEntryBlock().getFirstNonPHIOrDbg(); } -IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map, - bool resolve_vars, - lldb_private::IRExecutionUnit &execution_unit, - lldb_private::Stream &error_stream, - const char *func_name) : - ModulePass(ID), - m_resolve_vars(resolve_vars), - m_func_name(func_name), - m_module(NULL), - m_decl_map(decl_map), - m_CFStringCreateWithBytes(NULL), - m_sel_registerName(NULL), - m_intptr_ty(NULL), - m_error_stream(error_stream), - m_execution_unit(execution_unit), - m_result_store(NULL), - m_result_is_pointer(false), - m_reloc_placeholder(NULL), - m_entry_instruction_finder (FindEntryInstruction) -{ -} +IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, + bool resolve_vars, + lldb_private::IRExecutionUnit &execution_unit, + lldb_private::Stream &error_stream, + const char *func_name) + : ModulePass(ID), m_resolve_vars(resolve_vars), m_func_name(func_name), + m_module(NULL), m_decl_map(decl_map), m_CFStringCreateWithBytes(NULL), + m_sel_registerName(NULL), m_intptr_ty(NULL), m_error_stream(error_stream), + m_execution_unit(execution_unit), m_result_store(NULL), + m_result_is_pointer(false), m_reloc_placeholder(NULL), + m_entry_instruction_finder(FindEntryInstruction) {} /* Handy utility functions used at several places in the code */ -static std::string -PrintValue(const Value *value, bool truncate = false) -{ - std::string s; - if (value) - { - raw_string_ostream rso(s); - value->print(rso); - rso.flush(); - if (truncate) - s.resize(s.length() - 1); - } - return s; -} - -static std::string -PrintType(const llvm::Type *type, bool truncate = false) -{ - std::string s; +static std::string PrintValue(const Value *value, bool truncate = false) { + std::string s; + if (value) { raw_string_ostream rso(s); - type->print(rso); + value->print(rso); rso.flush(); if (truncate) - s.resize(s.length() - 1); - return s; + s.resize(s.length() - 1); + } + return s; } -IRForTarget::~IRForTarget() -{ +static std::string PrintType(const llvm::Type *type, bool truncate = false) { + std::string s; + raw_string_ostream rso(s); + type->print(rso); + rso.flush(); + if (truncate) + s.resize(s.length() - 1); + return s; } -bool -IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) -{ - llvm_function.setLinkage(GlobalValue::ExternalLinkage); +IRForTarget::~IRForTarget() {} - return true; +bool IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) { + llvm_function.setLinkage(GlobalValue::ExternalLinkage); + + return true; } -clang::NamedDecl * -IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module) -{ - NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs"); +clang::NamedDecl *IRForTarget::DeclForGlobal(const GlobalValue *global_val, + Module *module) { + NamedMDNode *named_metadata = + module->getNamedMetadata("clang.global.decl.ptrs"); - if (!named_metadata) - return NULL; + if (!named_metadata) + return NULL; - unsigned num_nodes = named_metadata->getNumOperands(); - unsigned node_index; + unsigned num_nodes = named_metadata->getNumOperands(); + unsigned node_index; - for (node_index = 0; - node_index < num_nodes; - ++node_index) - { - llvm::MDNode *metadata_node = dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index)); - if (!metadata_node) - return NULL; + for (node_index = 0; node_index < num_nodes; ++node_index) { + llvm::MDNode *metadata_node = + dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index)); + if (!metadata_node) + return NULL; - if (metadata_node->getNumOperands() != 2) - continue; + if (metadata_node->getNumOperands() != 2) + continue; - if (mdconst::dyn_extract_or_null<GlobalValue>(metadata_node->getOperand(0)) != global_val) - continue; + if (mdconst::dyn_extract_or_null<GlobalValue>( + metadata_node->getOperand(0)) != global_val) + continue; - ConstantInt *constant_int = mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1)); + ConstantInt *constant_int = + mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1)); - if (!constant_int) - return NULL; + if (!constant_int) + return NULL; - uintptr_t ptr = constant_int->getZExtValue(); + uintptr_t ptr = constant_int->getZExtValue(); - return reinterpret_cast<clang::NamedDecl *>(ptr); - } + return reinterpret_cast<clang::NamedDecl *>(ptr); + } - return NULL; + return NULL; } -clang::NamedDecl * -IRForTarget::DeclForGlobal (GlobalValue *global_val) -{ - return DeclForGlobal(global_val, m_module); +clang::NamedDecl *IRForTarget::DeclForGlobal(GlobalValue *global_val) { + return DeclForGlobal(global_val, m_module); } -bool -IRForTarget::CreateResultVariable (llvm::Function &llvm_function) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (!m_resolve_vars) - return true; + if (!m_resolve_vars) + return true; - // Find the result variable. If it doesn't exist, we can give up right here. + // Find the result variable. If it doesn't exist, we can give up right here. - ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); + ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable(); - std::string result_name_str; - const char *result_name = NULL; + std::string result_name_str; + const char *result_name = NULL; - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); - vi != ve; - ++vi) - { - result_name_str = vi->first().str(); - const char *value_name = result_name_str.c_str(); - - if (strstr(value_name, "$__lldb_expr_result_ptr") && - strncmp(value_name, "_ZGV", 4)) - { - result_name = value_name; - m_result_is_pointer = true; - break; - } + for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), + ve = value_symbol_table.end(); + vi != ve; ++vi) { + result_name_str = vi->first().str(); + const char *value_name = result_name_str.c_str(); - if (strstr(value_name, "$__lldb_expr_result") && - strncmp(value_name, "_ZGV", 4)) - { - result_name = value_name; - m_result_is_pointer = false; - break; - } + if (strstr(value_name, "$__lldb_expr_result_ptr") && + strncmp(value_name, "_ZGV", 4)) { + result_name = value_name; + m_result_is_pointer = true; + break; } - if (!result_name) - { - if (log) - log->PutCString("Couldn't find result variable"); - - return true; + if (strstr(value_name, "$__lldb_expr_result") && + strncmp(value_name, "_ZGV", 4)) { + result_name = value_name; + m_result_is_pointer = false; + break; } + } + if (!result_name) { if (log) - log->Printf("Result name: \"%s\"", result_name); - - Value *result_value = m_module->getNamedValue(result_name); + log->PutCString("Couldn't find result variable"); - if (!result_value) - { - if (log) - log->PutCString("Result variable had no data"); + return true; + } - m_error_stream.Printf("Internal error [IRForTarget]: Result variable's name (%s) exists, but not its definition\n", result_name); + if (log) + log->Printf("Result name: \"%s\"", result_name); - return false; - } + Value *result_value = m_module->getNamedValue(result_name); + if (!result_value) { if (log) - log->Printf("Found result in the IR: \"%s\"", PrintValue(result_value, false).c_str()); - - GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value); - - if (!result_global) - { - if (log) - log->PutCString("Result variable isn't a GlobalVariable"); - - m_error_stream.Printf("Internal error [IRForTarget]: Result variable (%s) is defined, but is not a global variable\n", result_name); + log->PutCString("Result variable had no data"); - return false; - } + m_error_stream.Printf("Internal error [IRForTarget]: Result variable's " + "name (%s) exists, but not its definition\n", + result_name); - clang::NamedDecl *result_decl = DeclForGlobal (result_global); - if (!result_decl) - { - if (log) - log->PutCString("Result variable doesn't have a corresponding Decl"); + return false; + } - m_error_stream.Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name); + if (log) + log->Printf("Found result in the IR: \"%s\"", + PrintValue(result_value, false).c_str()); - return false; - } + GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value); + if (!result_global) { if (log) - { - std::string decl_desc_str; - raw_string_ostream decl_desc_stream(decl_desc_str); - result_decl->print(decl_desc_stream); - decl_desc_stream.flush(); - - log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str()); - } + log->PutCString("Result variable isn't a GlobalVariable"); - clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl); - if (!result_var) - { - if (log) - log->PutCString("Result variable Decl isn't a VarDecl"); - - m_error_stream.Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name); - - return false; - } + m_error_stream.Printf("Internal error [IRForTarget]: Result variable (%s) " + "is defined, but is not a global variable\n", + result_name); - // Get the next available result name from m_decl_map and create the persistent - // variable for it - - // If the result is an Lvalue, it is emitted as a pointer; see - // ASTResultSynthesizer::SynthesizeBodyResult. - if (m_result_is_pointer) - { - clang::QualType pointer_qual_type = result_var->getType(); - const clang::Type *pointer_type = pointer_qual_type.getTypePtr(); - - const clang::PointerType *pointer_pointertype = pointer_type->getAs<clang::PointerType>(); - const clang::ObjCObjectPointerType *pointer_objcobjpointertype = pointer_type->getAs<clang::ObjCObjectPointerType>(); - - if (pointer_pointertype) - { - clang::QualType element_qual_type = pointer_pointertype->getPointeeType(); + return false; + } - m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), - lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); - } - else if (pointer_objcobjpointertype) - { - clang::QualType element_qual_type = clang::QualType(pointer_objcobjpointertype->getObjectType(), 0); + clang::NamedDecl *result_decl = DeclForGlobal(result_global); + if (!result_decl) { + if (log) + log->PutCString("Result variable doesn't have a corresponding Decl"); - m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), - lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); - } - else - { - if (log) - log->PutCString("Expected result to have pointer type, but it did not"); + m_error_stream.Printf("Internal error [IRForTarget]: Result variable (%s) " + "does not have a corresponding Clang entity\n", + result_name); - m_error_stream.Printf("Internal error [IRForTarget]: Lvalue result (%s) is not a pointer variable\n", result_name); + return false; + } - return false; - } - } - else - { - m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(), - lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); - } + if (log) { + std::string decl_desc_str; + raw_string_ostream decl_desc_stream(decl_desc_str); + result_decl->print(decl_desc_stream); + decl_desc_stream.flush(); + log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str()); + } - lldb::TargetSP target_sp (m_execution_unit.GetTarget()); - lldb_private::ExecutionContext exe_ctx (target_sp, true); - if (m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope()) == 0) - { - lldb_private::StreamString type_desc_stream; - m_result_type.DumpTypeDescription(&type_desc_stream); + clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl); + if (!result_var) { + if (log) + log->PutCString("Result variable Decl isn't a VarDecl"); - if (log) - log->Printf("Result type has size 0"); + m_error_stream.Printf("Internal error [IRForTarget]: Result variable " + "(%s)'s corresponding Clang entity isn't a " + "variable\n", + result_name); - m_error_stream.Printf("Error [IRForTarget]: Size of result type '%s' couldn't be determined\n", - type_desc_stream.GetData()); - return false; + return false; + } + + // Get the next available result name from m_decl_map and create the + // persistent + // variable for it + + // If the result is an Lvalue, it is emitted as a pointer; see + // ASTResultSynthesizer::SynthesizeBodyResult. + if (m_result_is_pointer) { + clang::QualType pointer_qual_type = result_var->getType(); + const clang::Type *pointer_type = pointer_qual_type.getTypePtr(); + + const clang::PointerType *pointer_pointertype = + pointer_type->getAs<clang::PointerType>(); + const clang::ObjCObjectPointerType *pointer_objcobjpointertype = + pointer_type->getAs<clang::ObjCObjectPointerType>(); + + if (pointer_pointertype) { + clang::QualType element_qual_type = pointer_pointertype->getPointeeType(); + + m_result_type = lldb_private::TypeFromParser( + element_qual_type.getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext( + &result_decl->getASTContext())); + } else if (pointer_objcobjpointertype) { + clang::QualType element_qual_type = + clang::QualType(pointer_objcobjpointertype->getObjectType(), 0); + + m_result_type = lldb_private::TypeFromParser( + element_qual_type.getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext( + &result_decl->getASTContext())); + } else { + if (log) + log->PutCString("Expected result to have pointer type, but it did not"); + + m_error_stream.Printf("Internal error [IRForTarget]: Lvalue result (%s) " + "is not a pointer variable\n", + result_name); + + return false; } + } else { + m_result_type = lldb_private::TypeFromParser( + result_var->getType().getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext( + &result_decl->getASTContext())); + } + + lldb::TargetSP target_sp(m_execution_unit.GetTarget()); + lldb_private::ExecutionContext exe_ctx(target_sp, true); + if (m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope()) == 0) { + lldb_private::StreamString type_desc_stream; + m_result_type.DumpTypeDescription(&type_desc_stream); if (log) - { - lldb_private::StreamString type_desc_stream; - m_result_type.DumpTypeDescription(&type_desc_stream); - - log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData()); - } + log->Printf("Result type has size 0"); - m_result_name = lldb_private::ConstString("$RESULT_NAME"); + m_error_stream.Printf("Error [IRForTarget]: Size of result type '%s' " + "couldn't be determined\n", + type_desc_stream.GetData()); + return false; + } - if (log) - log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64, - m_result_name.GetCString(), - m_result_type.GetByteSize(nullptr)); + if (log) { + lldb_private::StreamString type_desc_stream; + m_result_type.DumpTypeDescription(&type_desc_stream); - // Construct a new result global and set up its metadata + log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData()); + } - GlobalVariable *new_result_global = new GlobalVariable((*m_module), - result_global->getType()->getElementType(), - false, /* not constant */ - GlobalValue::ExternalLinkage, - NULL, /* no initializer */ - m_result_name.GetCString ()); + m_result_name = lldb_private::ConstString("$RESULT_NAME"); - // It's too late in compilation to create a new VarDecl for this, but we don't - // need to. We point the metadata at the old VarDecl. This creates an odd - // anomaly: a variable with a Value whose name is something like $0 and a - // Decl whose name is $__lldb_expr_result. This condition is handled in - // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is - // fixed up. + if (log) + log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64, + m_result_name.GetCString(), m_result_type.GetByteSize(nullptr)); - ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()), - reinterpret_cast<uint64_t>(result_decl), - false); + // Construct a new result global and set up its metadata - llvm::Metadata *values[2]; - values[0] = ConstantAsMetadata::get(new_result_global); - values[1] = ConstantAsMetadata::get(new_constant_int); + GlobalVariable *new_result_global = new GlobalVariable( + (*m_module), result_global->getType()->getElementType(), + false, /* not constant */ + GlobalValue::ExternalLinkage, NULL, /* no initializer */ + m_result_name.GetCString()); - ArrayRef<Metadata *> value_ref(values, 2); + // It's too late in compilation to create a new VarDecl for this, but we don't + // need to. We point the metadata at the old VarDecl. This creates an odd + // anomaly: a variable with a Value whose name is something like $0 and a + // Decl whose name is $__lldb_expr_result. This condition is handled in + // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is + // fixed up. - MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); - NamedMDNode *named_metadata = m_module->getNamedMetadata("clang.global.decl.ptrs"); - named_metadata->addOperand(persistent_global_md); + ConstantInt *new_constant_int = + ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()), + reinterpret_cast<uint64_t>(result_decl), false); - if (log) - log->Printf("Replacing \"%s\" with \"%s\"", - PrintValue(result_global).c_str(), - PrintValue(new_result_global).c_str()); + llvm::Metadata *values[2]; + values[0] = ConstantAsMetadata::get(new_result_global); + values[1] = ConstantAsMetadata::get(new_constant_int); - if (result_global->use_empty()) - { - // We need to synthesize a store for this variable, because otherwise - // there's nothing to put into its equivalent persistent variable. + ArrayRef<Metadata *> value_ref(values, 2); - BasicBlock &entry_block(llvm_function.getEntryBlock()); - Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg()); + MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); + NamedMDNode *named_metadata = + m_module->getNamedMetadata("clang.global.decl.ptrs"); + named_metadata->addOperand(persistent_global_md); - if (!first_entry_instruction) - return false; + if (log) + log->Printf("Replacing \"%s\" with \"%s\"", + PrintValue(result_global).c_str(), + PrintValue(new_result_global).c_str()); - if (!result_global->hasInitializer()) - { - if (log) - log->Printf("Couldn't find initializer for unused variable"); + if (result_global->use_empty()) { + // We need to synthesize a store for this variable, because otherwise + // there's nothing to put into its equivalent persistent variable. - m_error_stream.Printf("Internal error [IRForTarget]: Result variable (%s) has no writes and no initializer\n", result_name); + BasicBlock &entry_block(llvm_function.getEntryBlock()); + Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg()); - return false; - } + if (!first_entry_instruction) + return false; - Constant *initializer = result_global->getInitializer(); + if (!result_global->hasInitializer()) { + if (log) + log->Printf("Couldn't find initializer for unused variable"); - StoreInst *synthesized_store = new StoreInst(initializer, - new_result_global, - first_entry_instruction); + m_error_stream.Printf("Internal error [IRForTarget]: Result variable " + "(%s) has no writes and no initializer\n", + result_name); - if (log) - log->Printf("Synthesized result store \"%s\"\n", PrintValue(synthesized_store).c_str()); - } - else - { - result_global->replaceAllUsesWith(new_result_global); + return false; } - if (!m_decl_map->AddPersistentVariable(result_decl, - m_result_name, - m_result_type, - true, - m_result_is_pointer)) - return false; - - result_global->eraseFromParent(); - - return true; -} - -bool -IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str, - llvm::GlobalVariable *cstr) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - Type *ns_str_ty = ns_str->getType(); - - Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); - Type *i32_ty = Type::getInt32Ty(m_module->getContext()); - Type *i8_ty = Type::getInt8Ty(m_module->getContext()); + Constant *initializer = result_global->getInitializer(); - if (!m_CFStringCreateWithBytes) - { - lldb::addr_t CFStringCreateWithBytes_addr; - - static lldb_private::ConstString g_CFStringCreateWithBytes_str ("CFStringCreateWithBytes"); - - CFStringCreateWithBytes_addr = m_execution_unit.FindSymbol (g_CFStringCreateWithBytes_str); - if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS) - { - if (log) - log->PutCString("Couldn't find CFStringCreateWithBytes in the target"); - - m_error_stream.Printf("Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes\n"); + StoreInst *synthesized_store = + new StoreInst(initializer, new_result_global, first_entry_instruction); - return false; - } - - if (log) - log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, CFStringCreateWithBytes_addr); - - // Build the function type: - // - // CFStringRef CFStringCreateWithBytes ( - // CFAllocatorRef alloc, - // const UInt8 *bytes, - // CFIndex numBytes, - // CFStringEncoding encoding, - // Boolean isExternalRepresentation - // ); - // - // We make the following substitutions: - // - // CFStringRef -> i8* - // CFAllocatorRef -> i8* - // UInt8 * -> i8* - // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its pointer size for now) - // CFStringEncoding -> i32 - // Boolean -> i8 - - Type *arg_type_array[5]; - - arg_type_array[0] = i8_ptr_ty; - arg_type_array[1] = i8_ptr_ty; - arg_type_array[2] = m_intptr_ty; - arg_type_array[3] = i32_ty; - arg_type_array[4] = i8_ty; - - ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5); - - llvm::Type *CFSCWB_ty = FunctionType::get(ns_str_ty, CFSCWB_arg_types, false); - - // Build the constant containing the pointer to the function - PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty); - Constant *CFSCWB_addr_int = ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false); - m_CFStringCreateWithBytes = ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty); - } + if (log) + log->Printf("Synthesized result store \"%s\"\n", + PrintValue(synthesized_store).c_str()); + } else { + result_global->replaceAllUsesWith(new_result_global); + } + + if (!m_decl_map->AddPersistentVariable( + result_decl, m_result_name, m_result_type, true, m_result_is_pointer)) + return false; - ConstantDataSequential *string_array = NULL; + result_global->eraseFromParent(); - if (cstr) - string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer()); + return true; +} - Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty); - Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty) : Constant::getNullValue(i8_ptr_ty); - Constant *numBytes_arg = ConstantInt::get(m_intptr_ty, cstr ? string_array->getNumElements() - 1 : 0, false); - Constant *encoding_arg = ConstantInt::get(i32_ty, 0x0600, false); /* 0x0600 is kCFStringEncodingASCII */ - Constant *isExternal_arg = ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */ +bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, + llvm::GlobalVariable *cstr) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - Value *argument_array[5]; + Type *ns_str_ty = ns_str->getType(); - argument_array[0] = alloc_arg; - argument_array[1] = bytes_arg; - argument_array[2] = numBytes_arg; - argument_array[3] = encoding_arg; - argument_array[4] = isExternal_arg; + Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); + Type *i32_ty = Type::getInt32Ty(m_module->getContext()); + Type *i8_ty = Type::getInt8Ty(m_module->getContext()); - ArrayRef <Value *> CFSCWB_arguments(argument_array, 5); + if (!m_CFStringCreateWithBytes) { + lldb::addr_t CFStringCreateWithBytes_addr; - FunctionValueCache CFSCWB_Caller ([this, &CFSCWB_arguments] (llvm::Function *function)->llvm::Value * { - return CallInst::Create(m_CFStringCreateWithBytes, - CFSCWB_arguments, - "CFStringCreateWithBytes", - llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function))); - }); + static lldb_private::ConstString g_CFStringCreateWithBytes_str( + "CFStringCreateWithBytes"); - if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, m_entry_instruction_finder, m_error_stream)) - { - if (log) - log->PutCString("Couldn't replace the NSString with the result of the call"); + CFStringCreateWithBytes_addr = + m_execution_unit.FindSymbol(g_CFStringCreateWithBytes_str); + if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS) { + if (log) + log->PutCString("Couldn't find CFStringCreateWithBytes in the target"); - m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an Objective-C constant string with a dynamic string\n"); + m_error_stream.Printf("Error [IRForTarget]: Rewriting an Objective-C " + "constant string requires " + "CFStringCreateWithBytes\n"); - return false; + return false; } - ns_str->eraseFromParent(); - - return true; -} - -bool -IRForTarget::RewriteObjCConstStrings() -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); - - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); - vi != ve; - ++vi) - { - std::string value_name = vi->first().str(); - const char *value_name_cstr = value_name.c_str(); - - if (strstr(value_name_cstr, "_unnamed_cfstring_")) - { - Value *nsstring_value = vi->second; - - GlobalVariable *nsstring_global = dyn_cast<GlobalVariable>(nsstring_value); + if (log) + log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, + CFStringCreateWithBytes_addr); - if (!nsstring_global) - { - if (log) - log->PutCString("NSString variable is not a GlobalVariable"); + // Build the function type: + // + // CFStringRef CFStringCreateWithBytes ( + // CFAllocatorRef alloc, + // const UInt8 *bytes, + // CFIndex numBytes, + // CFStringEncoding encoding, + // Boolean isExternalRepresentation + // ); + // + // We make the following substitutions: + // + // CFStringRef -> i8* + // CFAllocatorRef -> i8* + // UInt8 * -> i8* + // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its + // pointer size for now) + // CFStringEncoding -> i32 + // Boolean -> i8 + + Type *arg_type_array[5]; + + arg_type_array[0] = i8_ptr_ty; + arg_type_array[1] = i8_ptr_ty; + arg_type_array[2] = m_intptr_ty; + arg_type_array[3] = i32_ty; + arg_type_array[4] = i8_ty; + + ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5); + + llvm::Type *CFSCWB_ty = + FunctionType::get(ns_str_ty, CFSCWB_arg_types, false); + + // Build the constant containing the pointer to the function + PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty); + Constant *CFSCWB_addr_int = + ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false); + m_CFStringCreateWithBytes = + ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty); + } + + ConstantDataSequential *string_array = NULL; + + if (cstr) + string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer()); + + Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty); + Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty) + : Constant::getNullValue(i8_ptr_ty); + Constant *numBytes_arg = ConstantInt::get( + m_intptr_ty, cstr ? string_array->getNumElements() - 1 : 0, false); + Constant *encoding_arg = ConstantInt::get( + i32_ty, 0x0600, false); /* 0x0600 is kCFStringEncodingASCII */ + Constant *isExternal_arg = + ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */ + + Value *argument_array[5]; + + argument_array[0] = alloc_arg; + argument_array[1] = bytes_arg; + argument_array[2] = numBytes_arg; + argument_array[3] = encoding_arg; + argument_array[4] = isExternal_arg; + + ArrayRef<Value *> CFSCWB_arguments(argument_array, 5); + + FunctionValueCache CFSCWB_Caller( + [this, &CFSCWB_arguments](llvm::Function *function) -> llvm::Value * { + return CallInst::Create( + m_CFStringCreateWithBytes, CFSCWB_arguments, + "CFStringCreateWithBytes", + llvm::cast<Instruction>( + m_entry_instruction_finder.GetValue(function))); + }); + + if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, + m_entry_instruction_finder, m_error_stream)) { + if (log) + log->PutCString( + "Couldn't replace the NSString with the result of the call"); - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C constant string is not a global variable\n"); + m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an " + "Objective-C constant string with a dynamic " + "string\n"); - return false; - } + return false; + } - if (!nsstring_global->hasInitializer()) - { - if (log) - log->PutCString("NSString variable does not have an initializer"); + ns_str->eraseFromParent(); - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C constant string does not have an initializer\n"); + return true; +} - return false; - } +bool IRForTarget::RewriteObjCConstStrings() { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - ConstantStruct *nsstring_struct = dyn_cast<ConstantStruct>(nsstring_global->getInitializer()); + ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable(); - if (!nsstring_struct) - { - if (log) - log->PutCString("NSString variable's initializer is not a ConstantStruct"); + for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), + ve = value_symbol_table.end(); + vi != ve; ++vi) { + std::string value_name = vi->first().str(); + const char *value_name_cstr = value_name.c_str(); - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C constant string is not a structure constant\n"); + if (strstr(value_name_cstr, "_unnamed_cfstring_")) { + Value *nsstring_value = vi->second; - return false; - } + GlobalVariable *nsstring_global = + dyn_cast<GlobalVariable>(nsstring_value); - // We expect the following structure: - // - // struct { - // int *isa; - // int flags; - // char *str; - // long length; - // }; + if (!nsstring_global) { + if (log) + log->PutCString("NSString variable is not a GlobalVariable"); - if (nsstring_struct->getNumOperands() != 4) - { - if (log) - log->Printf("NSString variable's initializer structure has an unexpected number of members. Should be 4, is %d", nsstring_struct->getNumOperands()); + m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " + "constant string is not a global variable\n"); - m_error_stream.Printf("Internal error [IRForTarget]: The struct for an Objective-C constant string is not as expected\n"); + return false; + } - return false; - } + if (!nsstring_global->hasInitializer()) { + if (log) + log->PutCString("NSString variable does not have an initializer"); - Constant *nsstring_member = nsstring_struct->getOperand(2); + m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " + "constant string does not have an initializer\n"); - if (!nsstring_member) - { - if (log) - log->PutCString("NSString initializer's str element was empty"); + return false; + } - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C constant string does not have a string initializer\n"); + ConstantStruct *nsstring_struct = + dyn_cast<ConstantStruct>(nsstring_global->getInitializer()); - return false; - } + if (!nsstring_struct) { + if (log) + log->PutCString( + "NSString variable's initializer is not a ConstantStruct"); - ConstantExpr *nsstring_expr = dyn_cast<ConstantExpr>(nsstring_member); + m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " + "constant string is not a structure constant\n"); - if (!nsstring_expr) - { - if (log) - log->PutCString("NSString initializer's str element is not a ConstantExpr"); + return false; + } + + // We expect the following structure: + // + // struct { + // int *isa; + // int flags; + // char *str; + // long length; + // }; + + if (nsstring_struct->getNumOperands() != 4) { + if (log) + log->Printf("NSString variable's initializer structure has an " + "unexpected number of members. Should be 4, is %d", + nsstring_struct->getNumOperands()); - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not constant\n"); + m_error_stream.Printf("Internal error [IRForTarget]: The struct for an " + "Objective-C constant string is not as " + "expected\n"); - return false; - } + return false; + } - if (nsstring_expr->getOpcode() != Instruction::GetElementPtr) - { - if (log) - log->Printf("NSString initializer's str element is not a GetElementPtr expression, it's a %s", nsstring_expr->getOpcodeName()); + Constant *nsstring_member = nsstring_struct->getOperand(2); - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not an array\n"); + if (!nsstring_member) { + if (log) + log->PutCString("NSString initializer's str element was empty"); - return false; - } + m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " + "constant string does not have a string " + "initializer\n"); - Constant *nsstring_cstr = nsstring_expr->getOperand(0); + return false; + } - GlobalVariable *cstr_global = dyn_cast<GlobalVariable>(nsstring_cstr); + ConstantExpr *nsstring_expr = dyn_cast<ConstantExpr>(nsstring_member); - if (!cstr_global) - { - if (log) - log->PutCString("NSString initializer's str element is not a GlobalVariable"); + if (!nsstring_expr) { + if (log) + log->PutCString( + "NSString initializer's str element is not a ConstantExpr"); - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a global\n"); + m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " + "constant string's string initializer is not " + "constant\n"); - return false; - } + return false; + } - if (!cstr_global->hasInitializer()) - { - if (log) - log->PutCString("NSString initializer's str element does not have an initializer"); + if (nsstring_expr->getOpcode() != Instruction::GetElementPtr) { + if (log) + log->Printf("NSString initializer's str element is not a " + "GetElementPtr expression, it's a %s", + nsstring_expr->getOpcodeName()); - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to initialized data\n"); + m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " + "constant string's string initializer is not an " + "array\n"); - return false; - } + return false; + } - /* - if (!cstr_array) - { - if (log) - log->PutCString("NSString initializer's str element is not a ConstantArray"); + Constant *nsstring_cstr = nsstring_expr->getOperand(0); - if (m_error_stream) - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to an array\n"); + GlobalVariable *cstr_global = dyn_cast<GlobalVariable>(nsstring_cstr); - return false; - } + if (!cstr_global) { + if (log) + log->PutCString( + "NSString initializer's str element is not a GlobalVariable"); - if (!cstr_array->isCString()) - { - if (log) - log->PutCString("NSString initializer's str element is not a C string array"); + m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " + "constant string's string initializer doesn't " + "point to a global\n"); - if (m_error_stream) - m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a C string\n"); + return false; + } - return false; - } - */ + if (!cstr_global->hasInitializer()) { + if (log) + log->PutCString("NSString initializer's str element does not have an " + "initializer"); - ConstantDataArray *cstr_array = dyn_cast<ConstantDataArray>(cstr_global->getInitializer()); + m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " + "constant string's string initializer doesn't " + "point to initialized data\n"); - if (log) - { - if (cstr_array) - log->Printf("Found NSString constant %s, which contains \"%s\"", value_name_cstr, cstr_array->getAsString().str().c_str()); - else - log->Printf("Found NSString constant %s, which contains \"\"", value_name_cstr); - } + return false; + } + + /* + if (!cstr_array) + { + if (log) + log->PutCString("NSString initializer's str element is not a + ConstantArray"); + + if (m_error_stream) + m_error_stream.Printf("Internal error [IRForTarget]: An + Objective-C constant string's string initializer doesn't point to an + array\n"); + + return false; + } + + if (!cstr_array->isCString()) + { + if (log) + log->PutCString("NSString initializer's str element is not a C + string array"); + + if (m_error_stream) + m_error_stream.Printf("Internal error [IRForTarget]: An + Objective-C constant string's string initializer doesn't point to a C + string\n"); + + return false; + } + */ + + ConstantDataArray *cstr_array = + dyn_cast<ConstantDataArray>(cstr_global->getInitializer()); + + if (log) { + if (cstr_array) + log->Printf("Found NSString constant %s, which contains \"%s\"", + value_name_cstr, cstr_array->getAsString().str().c_str()); + else + log->Printf("Found NSString constant %s, which contains \"\"", + value_name_cstr); + } - if (!cstr_array) - cstr_global = NULL; + if (!cstr_array) + cstr_global = NULL; - if (!RewriteObjCConstString(nsstring_global, cstr_global)) - { - if (log) - log->PutCString("Error rewriting the constant string"); + if (!RewriteObjCConstString(nsstring_global, cstr_global)) { + if (log) + log->PutCString("Error rewriting the constant string"); - // We don't print an error message here because RewriteObjCConstString has done so for us. + // We don't print an error message here because RewriteObjCConstString + // has done so for us. - return false; - } - } + return false; + } } + } - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); - vi != ve; - ++vi) - { - std::string value_name = vi->first().str(); - const char *value_name_cstr = value_name.c_str(); + for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), + ve = value_symbol_table.end(); + vi != ve; ++vi) { + std::string value_name = vi->first().str(); + const char *value_name_cstr = value_name.c_str(); - if (!strcmp(value_name_cstr, "__CFConstantStringClassReference")) - { - GlobalVariable *gv = dyn_cast<GlobalVariable>(vi->second); + if (!strcmp(value_name_cstr, "__CFConstantStringClassReference")) { + GlobalVariable *gv = dyn_cast<GlobalVariable>(vi->second); - if (!gv) - { - if (log) - log->PutCString("__CFConstantStringClassReference is not a global variable"); + if (!gv) { + if (log) + log->PutCString( + "__CFConstantStringClassReference is not a global variable"); - m_error_stream.Printf("Internal error [IRForTarget]: Found a CFConstantStringClassReference, but it is not a global object\n"); + m_error_stream.Printf("Internal error [IRForTarget]: Found a " + "CFConstantStringClassReference, but it is not a " + "global object\n"); - return false; - } + return false; + } - gv->eraseFromParent(); + gv->eraseFromParent(); - break; - } + break; } + } - return true; + return true; } -static bool IsObjCSelectorRef (Value *value) -{ - GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value); +static bool IsObjCSelectorRef(Value *value) { + GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value); - if (!global_variable || !global_variable->hasName() || !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_")) - return false; + if (!global_variable || !global_variable->hasName() || + !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_")) + return false; - return true; + return true; } // This function does not report errors; its callers are responsible. -bool -IRForTarget::RewriteObjCSelector (Instruction* selector_load) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - LoadInst *load = dyn_cast<LoadInst>(selector_load); - - if (!load) - return false; - - // Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as - // - // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*> - // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*> - // - // where %obj is the object pointer and %tmp is the selector. - // - // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_". - // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string. +bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - // Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target + LoadInst *load = dyn_cast<LoadInst>(selector_load); - GlobalVariable *_objc_selector_references_ = dyn_cast<GlobalVariable>(load->getPointerOperand()); + if (!load) + return false; - if (!_objc_selector_references_ || !_objc_selector_references_->hasInitializer()) - return false; + // Unpack the message name from the selector. In LLVM IR, an objc_msgSend + // gets represented as + // + // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*> + // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) + // ; <i8*> + // + // where %obj is the object pointer and %tmp is the selector. + // + // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called + // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_". + // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string. + + // Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) + // and get the string from its target + + GlobalVariable *_objc_selector_references_ = + dyn_cast<GlobalVariable>(load->getPointerOperand()); + + if (!_objc_selector_references_ || + !_objc_selector_references_->hasInitializer()) + return false; - Constant *osr_initializer = _objc_selector_references_->getInitializer(); + Constant *osr_initializer = _objc_selector_references_->getInitializer(); - ConstantExpr *osr_initializer_expr = dyn_cast<ConstantExpr>(osr_initializer); + ConstantExpr *osr_initializer_expr = dyn_cast<ConstantExpr>(osr_initializer); - if (!osr_initializer_expr || osr_initializer_expr->getOpcode() != Instruction::GetElementPtr) - return false; + if (!osr_initializer_expr || + osr_initializer_expr->getOpcode() != Instruction::GetElementPtr) + return false; - Value *osr_initializer_base = osr_initializer_expr->getOperand(0); + Value *osr_initializer_base = osr_initializer_expr->getOperand(0); - if (!osr_initializer_base) - return false; + if (!osr_initializer_base) + return false; - // Find the string's initializer (a ConstantArray) and get the string from it + // Find the string's initializer (a ConstantArray) and get the string from it - GlobalVariable *_objc_meth_var_name_ = dyn_cast<GlobalVariable>(osr_initializer_base); + GlobalVariable *_objc_meth_var_name_ = + dyn_cast<GlobalVariable>(osr_initializer_base); - if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer()) - return false; + if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer()) + return false; - Constant *omvn_initializer = _objc_meth_var_name_->getInitializer(); + Constant *omvn_initializer = _objc_meth_var_name_->getInitializer(); - ConstantDataArray *omvn_initializer_array = dyn_cast<ConstantDataArray>(omvn_initializer); + ConstantDataArray *omvn_initializer_array = + dyn_cast<ConstantDataArray>(omvn_initializer); - if (!omvn_initializer_array->isString()) - return false; + if (!omvn_initializer_array->isString()) + return false; - std::string omvn_initializer_string = omvn_initializer_array->getAsString(); + std::string omvn_initializer_string = omvn_initializer_array->getAsString(); - if (log) - log->Printf("Found Objective-C selector reference \"%s\"", omvn_initializer_string.c_str()); + if (log) + log->Printf("Found Objective-C selector reference \"%s\"", + omvn_initializer_string.c_str()); - // Construct a call to sel_registerName + // Construct a call to sel_registerName - if (!m_sel_registerName) - { - lldb::addr_t sel_registerName_addr; + if (!m_sel_registerName) { + lldb::addr_t sel_registerName_addr; - static lldb_private::ConstString g_sel_registerName_str ("sel_registerName"); - sel_registerName_addr = m_execution_unit.FindSymbol (g_sel_registerName_str); - if (sel_registerName_addr == LLDB_INVALID_ADDRESS) - return false; + static lldb_private::ConstString g_sel_registerName_str("sel_registerName"); + sel_registerName_addr = m_execution_unit.FindSymbol(g_sel_registerName_str); + if (sel_registerName_addr == LLDB_INVALID_ADDRESS) + return false; - if (log) - log->Printf("Found sel_registerName at 0x%" PRIx64, sel_registerName_addr); + if (log) + log->Printf("Found sel_registerName at 0x%" PRIx64, + sel_registerName_addr); - // Build the function type: struct objc_selector *sel_registerName(uint8_t*) + // Build the function type: struct objc_selector *sel_registerName(uint8_t*) - // The below code would be "more correct," but in actuality what's required is uint8_t* - //Type *sel_type = StructType::get(m_module->getContext()); - //Type *sel_ptr_type = PointerType::getUnqual(sel_type); - Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext()); + // The below code would be "more correct," but in actuality what's required + // is uint8_t* + // Type *sel_type = StructType::get(m_module->getContext()); + // Type *sel_ptr_type = PointerType::getUnqual(sel_type); + Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext()); - Type *type_array[1]; + Type *type_array[1]; - type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext()); + type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext()); - ArrayRef<Type *> srN_arg_types(type_array, 1); + ArrayRef<Type *> srN_arg_types(type_array, 1); - llvm::Type *srN_type = FunctionType::get(sel_ptr_type, srN_arg_types, false); + llvm::Type *srN_type = + FunctionType::get(sel_ptr_type, srN_arg_types, false); - // Build the constant containing the pointer to the function - PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type); - Constant *srN_addr_int = ConstantInt::get(m_intptr_ty, sel_registerName_addr, false); - m_sel_registerName = ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty); - } + // Build the constant containing the pointer to the function + PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type); + Constant *srN_addr_int = + ConstantInt::get(m_intptr_ty, sel_registerName_addr, false); + m_sel_registerName = ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty); + } - Value *argument_array[1]; + Value *argument_array[1]; - Constant *omvn_pointer = ConstantExpr::getBitCast(_objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext())); + Constant *omvn_pointer = ConstantExpr::getBitCast( + _objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext())); - argument_array[0] = omvn_pointer; + argument_array[0] = omvn_pointer; - ArrayRef<Value *> srN_arguments(argument_array, 1); + ArrayRef<Value *> srN_arguments(argument_array, 1); - CallInst *srN_call = CallInst::Create(m_sel_registerName, - srN_arguments, - "sel_registerName", - selector_load); + CallInst *srN_call = CallInst::Create(m_sel_registerName, srN_arguments, + "sel_registerName", selector_load); - // Replace the load with the call in all users + // Replace the load with the call in all users - selector_load->replaceAllUsesWith(srN_call); + selector_load->replaceAllUsesWith(srN_call); - selector_load->eraseFromParent(); + selector_load->eraseFromParent(); - return true; + return true; } -bool -IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool IRForTarget::RewriteObjCSelectors(BasicBlock &basic_block) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - BasicBlock::iterator ii; + BasicBlock::iterator ii; - typedef SmallVector <Instruction*, 2> InstrList; - typedef InstrList::iterator InstrIterator; + typedef SmallVector<Instruction *, 2> InstrList; + typedef InstrList::iterator InstrIterator; - InstrList selector_loads; + InstrList selector_loads; - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; + for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { + Instruction &inst = *ii; - if (LoadInst *load = dyn_cast<LoadInst>(&inst)) - if (IsObjCSelectorRef(load->getPointerOperand())) - selector_loads.push_back(&inst); - } + if (LoadInst *load = dyn_cast<LoadInst>(&inst)) + if (IsObjCSelectorRef(load->getPointerOperand())) + selector_loads.push_back(&inst); + } - InstrIterator iter; + InstrIterator iter; - for (iter = selector_loads.begin(); - iter != selector_loads.end(); - ++iter) - { - if (!RewriteObjCSelector(*iter)) - { - m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a static reference to an Objective-C selector to a dynamic reference\n"); + for (iter = selector_loads.begin(); iter != selector_loads.end(); ++iter) { + if (!RewriteObjCSelector(*iter)) { + m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a " + "static reference to an Objective-C selector to a " + "dynamic reference\n"); - if (log) - log->PutCString("Couldn't rewrite a reference to an Objective-C selector"); + if (log) + log->PutCString( + "Couldn't rewrite a reference to an Objective-C selector"); - return false; - } + return false; } + } - return true; + return true; } // This function does not report errors; its callers are responsible. -bool -IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc); + AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc); - MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr"); + MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr"); - if (!alloc_md || !alloc_md->getNumOperands()) - return false; + if (!alloc_md || !alloc_md->getNumOperands()) + return false; - ConstantInt *constant_int = mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0)); + ConstantInt *constant_int = + mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0)); - if (!constant_int) - return false; + if (!constant_int) + return false; - // We attempt to register this as a new persistent variable with the DeclMap. + // We attempt to register this as a new persistent variable with the DeclMap. - uintptr_t ptr = constant_int->getZExtValue(); + uintptr_t ptr = constant_int->getZExtValue(); - clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr); + clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr); - lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(), - lldb_private::ClangASTContext::GetASTContext(&decl->getASTContext())); + lldb_private::TypeFromParser result_decl_type( + decl->getType().getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext(&decl->getASTContext())); - StringRef decl_name (decl->getName()); - lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size()); - if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false)) - return false; + StringRef decl_name(decl->getName()); + lldb_private::ConstString persistent_variable_name(decl_name.data(), + decl_name.size()); + if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, + result_decl_type, false, false)) + return false; - GlobalVariable *persistent_global = new GlobalVariable((*m_module), - alloc->getType(), - false, /* not constant */ - GlobalValue::ExternalLinkage, - NULL, /* no initializer */ - alloc->getName().str().c_str()); + GlobalVariable *persistent_global = new GlobalVariable( + (*m_module), alloc->getType(), false, /* not constant */ + GlobalValue::ExternalLinkage, NULL, /* no initializer */ + alloc->getName().str().c_str()); - // What we're going to do here is make believe this was a regular old external - // variable. That means we need to make the metadata valid. + // What we're going to do here is make believe this was a regular old external + // variable. That means we need to make the metadata valid. - NamedMDNode *named_metadata = m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs"); + NamedMDNode *named_metadata = + m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs"); - llvm::Metadata *values[2]; - values[0] = ConstantAsMetadata::get(persistent_global); - values[1] = ConstantAsMetadata::get(constant_int); + llvm::Metadata *values[2]; + values[0] = ConstantAsMetadata::get(persistent_global); + values[1] = ConstantAsMetadata::get(constant_int); - ArrayRef<llvm::Metadata *> value_ref(values, 2); + ArrayRef<llvm::Metadata *> value_ref(values, 2); - MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); - named_metadata->addOperand(persistent_global_md); + MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); + named_metadata->addOperand(persistent_global_md); - // Now, since the variable is a pointer variable, we will drop in a load of that - // pointer variable. + // Now, since the variable is a pointer variable, we will drop in a load of + // that + // pointer variable. - LoadInst *persistent_load = new LoadInst (persistent_global, "", alloc); + LoadInst *persistent_load = new LoadInst(persistent_global, "", alloc); - if (log) - log->Printf("Replacing \"%s\" with \"%s\"", - PrintValue(alloc).c_str(), - PrintValue(persistent_load).c_str()); + if (log) + log->Printf("Replacing \"%s\" with \"%s\"", PrintValue(alloc).c_str(), + PrintValue(persistent_load).c_str()); - alloc->replaceAllUsesWith(persistent_load); - alloc->eraseFromParent(); + alloc->replaceAllUsesWith(persistent_load); + alloc->eraseFromParent(); - return true; + return true; } -bool -IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) -{ - if (!m_resolve_vars) - return true; +bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { + if (!m_resolve_vars) + return true; - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - BasicBlock::iterator ii; + BasicBlock::iterator ii; - typedef SmallVector <Instruction*, 2> InstrList; - typedef InstrList::iterator InstrIterator; + typedef SmallVector<Instruction *, 2> InstrList; + typedef InstrList::iterator InstrIterator; - InstrList pvar_allocs; + InstrList pvar_allocs; - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; + for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { + Instruction &inst = *ii; - if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) - { - llvm::StringRef alloc_name = alloc->getName(); + if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) { + llvm::StringRef alloc_name = alloc->getName(); - if (alloc_name.startswith("$") && - !alloc_name.startswith("$__lldb")) - { - if (alloc_name.find_first_of("0123456789") == 1) - { - if (log) - log->Printf("Rejecting a numeric persistent variable."); + if (alloc_name.startswith("$") && !alloc_name.startswith("$__lldb")) { + if (alloc_name.find_first_of("0123456789") == 1) { + if (log) + log->Printf("Rejecting a numeric persistent variable."); - m_error_stream.Printf("Error [IRForTarget]: Names starting with $0, $1, ... are reserved for use as result names\n"); + m_error_stream.Printf("Error [IRForTarget]: Names starting with $0, " + "$1, ... are reserved for use as result " + "names\n"); - return false; - } - - pvar_allocs.push_back(alloc); - } + return false; } + + pvar_allocs.push_back(alloc); + } } + } - InstrIterator iter; + InstrIterator iter; - for (iter = pvar_allocs.begin(); - iter != pvar_allocs.end(); - ++iter) - { - if (!RewritePersistentAlloc(*iter)) - { - m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable\n"); + for (iter = pvar_allocs.begin(); iter != pvar_allocs.end(); ++iter) { + if (!RewritePersistentAlloc(*iter)) { + m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " + "the creation of a persistent variable\n"); - if (log) - log->PutCString("Couldn't rewrite the creation of a persistent variable"); + if (log) + log->PutCString( + "Couldn't rewrite the creation of a persistent variable"); - return false; - } + return false; } + } - return true; + return true; } -bool -IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer) -{ - if (!initializer) - return true; +bool IRForTarget::MaterializeInitializer(uint8_t *data, Constant *initializer) { + if (!initializer) + return true; - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log && log->GetVerbose()) - log->Printf(" MaterializeInitializer(%p, %s)", (void *)data, PrintValue(initializer).c_str()); + if (log && log->GetVerbose()) + log->Printf(" MaterializeInitializer(%p, %s)", (void *)data, + PrintValue(initializer).c_str()); - Type *initializer_type = initializer->getType(); + Type *initializer_type = initializer->getType(); - if (ConstantInt *int_initializer = dyn_cast<ConstantInt>(initializer)) - { - size_t constant_size = m_target_data->getTypeStoreSize(initializer_type); - lldb_private::Scalar scalar = int_initializer->getValue().zextOrTrunc(llvm::NextPowerOf2(constant_size) * 8); + if (ConstantInt *int_initializer = dyn_cast<ConstantInt>(initializer)) { + size_t constant_size = m_target_data->getTypeStoreSize(initializer_type); + lldb_private::Scalar scalar = int_initializer->getValue().zextOrTrunc( + llvm::NextPowerOf2(constant_size) * 8); - lldb_private::Error get_data_error; - if (!scalar.GetAsMemoryData(data, constant_size, lldb_private::endian::InlHostByteOrder(), get_data_error)) - return false; + lldb_private::Error get_data_error; + if (!scalar.GetAsMemoryData(data, constant_size, + lldb_private::endian::InlHostByteOrder(), + get_data_error)) + return false; - return true; - } - else if (ConstantDataArray *array_initializer = dyn_cast<ConstantDataArray>(initializer)) - { - if (array_initializer->isString()) - { - std::string array_initializer_string = array_initializer->getAsString(); - memcpy (data, array_initializer_string.c_str(), m_target_data->getTypeStoreSize(initializer_type)); - } - else - { - ArrayType *array_initializer_type = array_initializer->getType(); - Type *array_element_type = array_initializer_type->getElementType(); - - size_t element_size = m_target_data->getTypeAllocSize(array_element_type); - - for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i) - { - Value *operand_value = array_initializer->getOperand(i); - Constant *operand_constant = dyn_cast<Constant>(operand_value); - - if (!operand_constant) - return false; - - if (!MaterializeInitializer(data + (i * element_size), operand_constant)) - return false; - } - } - return true; - } - else if (ConstantStruct *struct_initializer = dyn_cast<ConstantStruct>(initializer)) - { - StructType *struct_initializer_type = struct_initializer->getType(); - const StructLayout *struct_layout = m_target_data->getStructLayout(struct_initializer_type); - - for (unsigned i = 0; - i < struct_initializer->getNumOperands(); - ++i) - { - if (!MaterializeInitializer(data + struct_layout->getElementOffset(i), struct_initializer->getOperand(i))) - return false; - } - return true; + return true; + } else if (ConstantDataArray *array_initializer = + dyn_cast<ConstantDataArray>(initializer)) { + if (array_initializer->isString()) { + std::string array_initializer_string = array_initializer->getAsString(); + memcpy(data, array_initializer_string.c_str(), + m_target_data->getTypeStoreSize(initializer_type)); + } else { + ArrayType *array_initializer_type = array_initializer->getType(); + Type *array_element_type = array_initializer_type->getElementType(); + + size_t element_size = m_target_data->getTypeAllocSize(array_element_type); + + for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i) { + Value *operand_value = array_initializer->getOperand(i); + Constant *operand_constant = dyn_cast<Constant>(operand_value); + + if (!operand_constant) + return false; + + if (!MaterializeInitializer(data + (i * element_size), + operand_constant)) + return false; + } } - else if (isa<ConstantAggregateZero>(initializer)) - { - memset(data, 0, m_target_data->getTypeStoreSize(initializer_type)); - return true; + return true; + } else if (ConstantStruct *struct_initializer = + dyn_cast<ConstantStruct>(initializer)) { + StructType *struct_initializer_type = struct_initializer->getType(); + const StructLayout *struct_layout = + m_target_data->getStructLayout(struct_initializer_type); + + for (unsigned i = 0; i < struct_initializer->getNumOperands(); ++i) { + if (!MaterializeInitializer(data + struct_layout->getElementOffset(i), + struct_initializer->getOperand(i))) + return false; } - return false; + return true; + } else if (isa<ConstantAggregateZero>(initializer)) { + memset(data, 0, m_target_data->getTypeStoreSize(initializer_type)); + return true; + } + return false; } // This function does not report errors; its callers are responsible. -bool -IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str()); - - if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) - { - switch (constant_expr->getOpcode()) - { - default: - break; - case Instruction::GetElementPtr: - case Instruction::BitCast: - Value *s = constant_expr->getOperand(0); - if (!MaybeHandleVariable(s)) - return false; - } +bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str()); + + if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) { + switch (constant_expr->getOpcode()) { + default: + break; + case Instruction::GetElementPtr: + case Instruction::BitCast: + Value *s = constant_expr->getOperand(0); + if (!MaybeHandleVariable(s)) + return false; } - else if (GlobalVariable *global_variable = dyn_cast<GlobalVariable>(llvm_value_ptr)) - { - if (!GlobalValue::isExternalLinkage(global_variable->getLinkage())) - return true; - - clang::NamedDecl *named_decl = DeclForGlobal(global_variable); - - if (!named_decl) - { - if (IsObjCSelectorRef(llvm_value_ptr)) - return true; - - if (!global_variable->hasExternalLinkage()) - return true; + } else if (GlobalVariable *global_variable = + dyn_cast<GlobalVariable>(llvm_value_ptr)) { + if (!GlobalValue::isExternalLinkage(global_variable->getLinkage())) + return true; - if (log) - log->Printf("Found global variable \"%s\" without metadata", global_variable->getName().str().c_str()); + clang::NamedDecl *named_decl = DeclForGlobal(global_variable); - return false; - } - - std::string name (named_decl->getName().str()); - - clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl); - if (value_decl == NULL) - return false; + if (!named_decl) { + if (IsObjCSelectorRef(llvm_value_ptr)) + return true; - lldb_private::CompilerType compiler_type(&value_decl->getASTContext(), value_decl->getType()); - - const Type *value_type = NULL; - - if (name[0] == '$') - { - // The $__lldb_expr_result name indicates the return value has allocated as - // a static variable. Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, - // accesses to this static variable need to be redirected to the result of dereferencing - // a pointer that is passed in as one of the arguments. - // - // Consequently, when reporting the size of the type, we report a pointer type pointing - // to the type of $__lldb_expr_result, not the type itself. - // - // We also do this for any user-declared persistent variables. - compiler_type = compiler_type.GetPointerType(); - value_type = PointerType::get(global_variable->getType(), 0); - } - else - { - value_type = global_variable->getType(); - } + if (!global_variable->hasExternalLinkage()) + return true; - const uint64_t value_size = compiler_type.GetByteSize(nullptr); - lldb::offset_t value_alignment = (compiler_type.GetTypeBitAlign() + 7ull) / 8ull; + if (log) + log->Printf("Found global variable \"%s\" without metadata", + global_variable->getName().str().c_str()); - if (log) - { - log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRIu64 "]", - name.c_str(), lldb_private::ClangUtil::GetQualType(compiler_type).getAsString().c_str(), - PrintType(value_type).c_str(), value_size, value_alignment); - } + return false; + } + std::string name(named_decl->getName().str()); + + clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl); + if (value_decl == NULL) + return false; + + lldb_private::CompilerType compiler_type(&value_decl->getASTContext(), + value_decl->getType()); + + const Type *value_type = NULL; + + if (name[0] == '$') { + // The $__lldb_expr_result name indicates the return value has allocated + // as + // a static variable. Per the comment at + // ASTResultSynthesizer::SynthesizeBodyResult, + // accesses to this static variable need to be redirected to the result of + // dereferencing + // a pointer that is passed in as one of the arguments. + // + // Consequently, when reporting the size of the type, we report a pointer + // type pointing + // to the type of $__lldb_expr_result, not the type itself. + // + // We also do this for any user-declared persistent variables. + compiler_type = compiler_type.GetPointerType(); + value_type = PointerType::get(global_variable->getType(), 0); + } else { + value_type = global_variable->getType(); + } - if (named_decl && !m_decl_map->AddValueToStruct(named_decl, - lldb_private::ConstString (name.c_str()), - llvm_value_ptr, - value_size, - value_alignment)) - { - if (!global_variable->hasExternalLinkage()) - return true; - else - return true; - } + const uint64_t value_size = compiler_type.GetByteSize(nullptr); + lldb::offset_t value_alignment = + (compiler_type.GetTypeBitAlign() + 7ull) / 8ull; + + if (log) { + log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 + ", align %" PRIu64 "]", + name.c_str(), + lldb_private::ClangUtil::GetQualType(compiler_type) + .getAsString() + .c_str(), + PrintType(value_type).c_str(), value_size, value_alignment); } - else if (dyn_cast<llvm::Function>(llvm_value_ptr)) - { - if (log) - log->Printf("Function pointers aren't handled right now"); - return false; + if (named_decl && + !m_decl_map->AddValueToStruct( + named_decl, lldb_private::ConstString(name.c_str()), llvm_value_ptr, + value_size, value_alignment)) { + if (!global_variable->hasExternalLinkage()) + return true; + else + return true; } + } else if (dyn_cast<llvm::Function>(llvm_value_ptr)) { + if (log) + log->Printf("Function pointers aren't handled right now"); - return true; + return false; + } + + return true; } // This function does not report errors; its callers are responsible. -bool -IRForTarget::HandleSymbol (Value *symbol) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool IRForTarget::HandleSymbol(Value *symbol) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - lldb_private::ConstString name(symbol->getName().str().c_str()); + lldb_private::ConstString name(symbol->getName().str().c_str()); - lldb::addr_t symbol_addr = m_decl_map->GetSymbolAddress (name, lldb::eSymbolTypeAny); + lldb::addr_t symbol_addr = + m_decl_map->GetSymbolAddress(name, lldb::eSymbolTypeAny); - if (symbol_addr == LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf ("Symbol \"%s\" had no address", name.GetCString()); + if (symbol_addr == LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("Symbol \"%s\" had no address", name.GetCString()); - return false; - } + return false; + } - if (log) - log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr); + if (log) + log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr); - Type *symbol_type = symbol->getType(); + Type *symbol_type = symbol->getType(); - Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false); + Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false); - Value *symbol_addr_ptr = ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type); + Value *symbol_addr_ptr = + ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type); - if (log) - log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), PrintValue(symbol_addr_ptr).c_str()); + if (log) + log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), + PrintValue(symbol_addr_ptr).c_str()); - symbol->replaceAllUsesWith(symbol_addr_ptr); + symbol->replaceAllUsesWith(symbol_addr_ptr); - return true; + return true; } -bool -IRForTarget::MaybeHandleCallArguments (CallInst *Old) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool IRForTarget::MaybeHandleCallArguments(CallInst *Old) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str()); + if (log) + log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str()); - for (unsigned op_index = 0, num_ops = Old->getNumArgOperands(); - op_index < num_ops; - ++op_index) - if (!MaybeHandleVariable(Old->getArgOperand(op_index))) // conservatively believe that this is a store - { - m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite one of the arguments of a function call.\n"); + for (unsigned op_index = 0, num_ops = Old->getNumArgOperands(); + op_index < num_ops; ++op_index) + if (!MaybeHandleVariable(Old->getArgOperand( + op_index))) // conservatively believe that this is a store + { + m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " + "one of the arguments of a function call.\n"); - return false; - } + return false; + } - return true; + return true; } -bool -IRForTarget::HandleObjCClass(Value *classlist_reference) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool IRForTarget::HandleObjCClass(Value *classlist_reference) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - GlobalVariable *global_variable = dyn_cast<GlobalVariable>(classlist_reference); + GlobalVariable *global_variable = + dyn_cast<GlobalVariable>(classlist_reference); - if (!global_variable) - return false; + if (!global_variable) + return false; - Constant *initializer = global_variable->getInitializer(); + Constant *initializer = global_variable->getInitializer(); - if (!initializer) - return false; + if (!initializer) + return false; - if (!initializer->hasName()) - return false; + if (!initializer->hasName()) + return false; - StringRef name(initializer->getName()); - lldb_private::ConstString name_cstr(name.str().c_str()); - lldb::addr_t class_ptr = m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass); + StringRef name(initializer->getName()); + lldb_private::ConstString name_cstr(name.str().c_str()); + lldb::addr_t class_ptr = + m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass); - if (log) - log->Printf("Found reference to Objective-C class %s (0x%llx)", name_cstr.AsCString(), (unsigned long long)class_ptr); + if (log) + log->Printf("Found reference to Objective-C class %s (0x%llx)", + name_cstr.AsCString(), (unsigned long long)class_ptr); - if (class_ptr == LLDB_INVALID_ADDRESS) - return false; + if (class_ptr == LLDB_INVALID_ADDRESS) + return false; - if (global_variable->use_empty()) - return false; + if (global_variable->use_empty()) + return false; - SmallVector<LoadInst *, 2> load_instructions; + SmallVector<LoadInst *, 2> load_instructions; - for (llvm::User *u : global_variable->users()) - { - if (LoadInst *load_instruction = dyn_cast<LoadInst>(u)) - load_instructions.push_back(load_instruction); - } + for (llvm::User *u : global_variable->users()) { + if (LoadInst *load_instruction = dyn_cast<LoadInst>(u)) + load_instructions.push_back(load_instruction); + } - if (load_instructions.empty()) - return false; + if (load_instructions.empty()) + return false; - Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr); + Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr); - for (LoadInst *load_instruction : load_instructions) - { - Constant *class_bitcast = ConstantExpr::getIntToPtr(class_addr, load_instruction->getType()); + for (LoadInst *load_instruction : load_instructions) { + Constant *class_bitcast = + ConstantExpr::getIntToPtr(class_addr, load_instruction->getType()); - load_instruction->replaceAllUsesWith(class_bitcast); + load_instruction->replaceAllUsesWith(class_bitcast); - load_instruction->eraseFromParent(); - } + load_instruction->eraseFromParent(); + } - return true; + return true; } -bool -IRForTarget::RemoveCXAAtExit (BasicBlock &basic_block) -{ - BasicBlock::iterator ii; +bool IRForTarget::RemoveCXAAtExit(BasicBlock &basic_block) { + BasicBlock::iterator ii; - std::vector<CallInst *> calls_to_remove; + std::vector<CallInst *> calls_to_remove; - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; + for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { + Instruction &inst = *ii; - CallInst *call = dyn_cast<CallInst>(&inst); + CallInst *call = dyn_cast<CallInst>(&inst); - // MaybeHandleCallArguments handles error reporting; we are silent here - if (!call) - continue; + // MaybeHandleCallArguments handles error reporting; we are silent here + if (!call) + continue; - bool remove = false; + bool remove = false; - llvm::Function *func = call->getCalledFunction(); + llvm::Function *func = call->getCalledFunction(); - if (func && func->getName() == "__cxa_atexit") - remove = true; + if (func && func->getName() == "__cxa_atexit") + remove = true; - llvm::Value *val = call->getCalledValue(); + llvm::Value *val = call->getCalledValue(); - if (val && val->getName() == "__cxa_atexit") - remove = true; + if (val && val->getName() == "__cxa_atexit") + remove = true; - if (remove) - calls_to_remove.push_back(call); - } + if (remove) + calls_to_remove.push_back(call); + } - for (std::vector<CallInst *>::iterator ci = calls_to_remove.begin(), ce = calls_to_remove.end(); - ci != ce; - ++ci) - { - (*ci)->eraseFromParent(); - } + for (std::vector<CallInst *>::iterator ci = calls_to_remove.begin(), + ce = calls_to_remove.end(); + ci != ce; ++ci) { + (*ci)->eraseFromParent(); + } - return true; + return true; } -bool -IRForTarget::ResolveCalls(BasicBlock &basic_block) -{ - ///////////////////////////////////////////////////////////////////////// - // Prepare the current basic block for execution in the remote process - // +bool IRForTarget::ResolveCalls(BasicBlock &basic_block) { + ///////////////////////////////////////////////////////////////////////// + // Prepare the current basic block for execution in the remote process + // - BasicBlock::iterator ii; + BasicBlock::iterator ii; - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; + for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { + Instruction &inst = *ii; - CallInst *call = dyn_cast<CallInst>(&inst); + CallInst *call = dyn_cast<CallInst>(&inst); - // MaybeHandleCallArguments handles error reporting; we are silent here - if (call && !MaybeHandleCallArguments(call)) - return false; - } + // MaybeHandleCallArguments handles error reporting; we are silent here + if (call && !MaybeHandleCallArguments(call)) + return false; + } - return true; + return true; } -bool -IRForTarget::ResolveExternals (Function &llvm_function) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool IRForTarget::ResolveExternals(Function &llvm_function) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - for (GlobalVariable &global_var : m_module->globals()) - { - std::string global_name = global_var.getName().str(); + for (GlobalVariable &global_var : m_module->globals()) { + std::string global_name = global_var.getName().str(); - if (log) - log->Printf("Examining %s, DeclForGlobalValue returns %p", - global_name.c_str(), - static_cast<void*>(DeclForGlobal(&global_var))); + if (log) + log->Printf("Examining %s, DeclForGlobalValue returns %p", + global_name.c_str(), + static_cast<void *>(DeclForGlobal(&global_var))); - if (global_name.find("OBJC_IVAR") == 0) - { - if (!HandleSymbol(&global_var)) - { - m_error_stream.Printf("Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s\n", global_name.c_str()); + if (global_name.find("OBJC_IVAR") == 0) { + if (!HandleSymbol(&global_var)) { + m_error_stream.Printf("Error [IRForTarget]: Couldn't find Objective-C " + "indirect ivar symbol %s\n", + global_name.c_str()); - return false; - } - } - else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != global_name.npos) - { - if (!HandleObjCClass(&global_var)) - { - m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); + return false; + } + } else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != + global_name.npos) { + if (!HandleObjCClass(&global_var)) { + m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class " + "for an Objective-C static method call\n"); - return false; - } - } - else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != global_name.npos) - { - if (!HandleObjCClass(&global_var)) - { - m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); + return false; + } + } else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != + global_name.npos) { + if (!HandleObjCClass(&global_var)) { + m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class " + "for an Objective-C static method call\n"); - return false; - } - } - else if (DeclForGlobal(&global_var)) - { - if (!MaybeHandleVariable (&global_var)) - { - m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite external variable %s\n", global_name.c_str()); + return false; + } + } else if (DeclForGlobal(&global_var)) { + if (!MaybeHandleVariable(&global_var)) { + m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " + "external variable %s\n", + global_name.c_str()); - return false; - } - } + return false; + } } + } - return true; + return true; } -static bool isGuardVariableRef(Value *V) -{ - Constant *Old = NULL; +static bool isGuardVariableRef(Value *V) { + Constant *Old = NULL; - if (!(Old = dyn_cast<Constant>(V))) - return false; + if (!(Old = dyn_cast<Constant>(V))) + return false; - ConstantExpr *CE = NULL; + ConstantExpr *CE = NULL; - if ((CE = dyn_cast<ConstantExpr>(V))) - { - if (CE->getOpcode() != Instruction::BitCast) - return false; + if ((CE = dyn_cast<ConstantExpr>(V))) { + if (CE->getOpcode() != Instruction::BitCast) + return false; - Old = CE->getOperand(0); - } + Old = CE->getOperand(0); + } - GlobalVariable *GV = dyn_cast<GlobalVariable>(Old); + GlobalVariable *GV = dyn_cast<GlobalVariable>(Old); - if (!GV || !GV->hasName() || - (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable - !GV->getName().endswith("@4IA"))) // Microsoft ABI guard variable - { - return false; - } + if (!GV || !GV->hasName() || + (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable + !GV->getName().endswith("@4IA"))) // Microsoft ABI guard variable + { + return false; + } - return true; + return true; } -void -IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction* guard_load) -{ - Constant *zero(Constant::getNullValue(guard_load->getType())); - guard_load->replaceAllUsesWith(zero); - guard_load->eraseFromParent(); +void IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction *guard_load) { + Constant *zero(Constant::getNullValue(guard_load->getType())); + guard_load->replaceAllUsesWith(zero); + guard_load->eraseFromParent(); } -static void ExciseGuardStore(Instruction* guard_store) -{ - guard_store->eraseFromParent(); +static void ExciseGuardStore(Instruction *guard_store) { + guard_store->eraseFromParent(); } -bool -IRForTarget::RemoveGuards(BasicBlock &basic_block) -{ - /////////////////////////////////////////////////////// - // Eliminate any reference to guard variables found. - // +bool IRForTarget::RemoveGuards(BasicBlock &basic_block) { + /////////////////////////////////////////////////////// + // Eliminate any reference to guard variables found. + // - BasicBlock::iterator ii; + BasicBlock::iterator ii; - typedef SmallVector <Instruction*, 2> InstrList; - typedef InstrList::iterator InstrIterator; + typedef SmallVector<Instruction *, 2> InstrList; + typedef InstrList::iterator InstrIterator; - InstrList guard_loads; - InstrList guard_stores; + InstrList guard_loads; + InstrList guard_stores; - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; + for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { + Instruction &inst = *ii; - if (LoadInst *load = dyn_cast<LoadInst>(&inst)) - if (isGuardVariableRef(load->getPointerOperand())) - guard_loads.push_back(&inst); + if (LoadInst *load = dyn_cast<LoadInst>(&inst)) + if (isGuardVariableRef(load->getPointerOperand())) + guard_loads.push_back(&inst); - if (StoreInst *store = dyn_cast<StoreInst>(&inst)) - if (isGuardVariableRef(store->getPointerOperand())) - guard_stores.push_back(&inst); - } + if (StoreInst *store = dyn_cast<StoreInst>(&inst)) + if (isGuardVariableRef(store->getPointerOperand())) + guard_stores.push_back(&inst); + } - InstrIterator iter; + InstrIterator iter; - for (iter = guard_loads.begin(); - iter != guard_loads.end(); - ++iter) - TurnGuardLoadIntoZero(*iter); + for (iter = guard_loads.begin(); iter != guard_loads.end(); ++iter) + TurnGuardLoadIntoZero(*iter); - for (iter = guard_stores.begin(); - iter != guard_stores.end(); - ++iter) - ExciseGuardStore(*iter); + for (iter = guard_stores.begin(); iter != guard_stores.end(); ++iter) + ExciseGuardStore(*iter); - return true; + return true; } // This function does not report errors; its callers are responsible. -bool -IRForTarget::UnfoldConstant(Constant *old_constant, - llvm::Function *llvm_function, - FunctionValueCache &value_maker, - FunctionValueCache &entry_instruction_finder, - lldb_private::Stream &error_stream) -{ - SmallVector<User*, 16> users; - - // We do this because the use list might change, invalidating our iterator. - // Much better to keep a work list ourselves. - for (llvm::User *u : old_constant->users()) - users.push_back(u); - - for (size_t i = 0; - i < users.size(); - ++i) - { - User *user = users[i]; - - if (Constant *constant = dyn_cast<Constant>(user)) - { - // synthesize a new non-constant equivalent of the constant - - if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) - { - switch (constant_expr->getOpcode()) - { - default: - error_stream.Printf("error [IRForTarget internal]: Unhandled constant expression type: \"%s\"", PrintValue(constant_expr).c_str()); - return false; - case Instruction::BitCast: - { - FunctionValueCache bit_cast_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { - // UnaryExpr - // OperandList[0] is value - - if (constant_expr->getOperand(0) != old_constant) - return constant_expr; - - return new BitCastInst(value_maker.GetValue(function), - constant_expr->getType(), - "", - llvm::cast<Instruction>(entry_instruction_finder.GetValue(function))); - }); - - if (!UnfoldConstant(constant_expr, llvm_function, bit_cast_maker, entry_instruction_finder, error_stream)) - return false; - } - break; - case Instruction::GetElementPtr: - { - // GetElementPtrConstantExpr - // OperandList[0] is base - // OperandList[1]... are indices - - FunctionValueCache get_element_pointer_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { - Value *ptr = constant_expr->getOperand(0); - - if (ptr == old_constant) - ptr = value_maker.GetValue(function); - - std::vector<Value*> index_vector; - - unsigned operand_index; - unsigned num_operands = constant_expr->getNumOperands(); - - for (operand_index = 1; - operand_index < num_operands; - ++operand_index) - { - Value *operand = constant_expr->getOperand(operand_index); - - if (operand == old_constant) - operand = value_maker.GetValue(function); - - index_vector.push_back(operand); - } - - ArrayRef <Value*> indices(index_vector); - - return GetElementPtrInst::Create(nullptr, ptr, indices, "", llvm::cast<Instruction>(entry_instruction_finder.GetValue(function))); - }); - - if (!UnfoldConstant(constant_expr, llvm_function, get_element_pointer_maker, entry_instruction_finder, error_stream)) - return false; - } - break; +bool IRForTarget::UnfoldConstant(Constant *old_constant, + llvm::Function *llvm_function, + FunctionValueCache &value_maker, + FunctionValueCache &entry_instruction_finder, + lldb_private::Stream &error_stream) { + SmallVector<User *, 16> users; + + // We do this because the use list might change, invalidating our iterator. + // Much better to keep a work list ourselves. + for (llvm::User *u : old_constant->users()) + users.push_back(u); + + for (size_t i = 0; i < users.size(); ++i) { + User *user = users[i]; + + if (Constant *constant = dyn_cast<Constant>(user)) { + // synthesize a new non-constant equivalent of the constant + + if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) { + switch (constant_expr->getOpcode()) { + default: + error_stream.Printf("error [IRForTarget internal]: Unhandled " + "constant expression type: \"%s\"", + PrintValue(constant_expr).c_str()); + return false; + case Instruction::BitCast: { + FunctionValueCache bit_cast_maker( + [&value_maker, &entry_instruction_finder, old_constant, + constant_expr](llvm::Function *function) -> llvm::Value * { + // UnaryExpr + // OperandList[0] is value + + if (constant_expr->getOperand(0) != old_constant) + return constant_expr; + + return new BitCastInst( + value_maker.GetValue(function), constant_expr->getType(), + "", llvm::cast<Instruction>( + entry_instruction_finder.GetValue(function))); + }); + + if (!UnfoldConstant(constant_expr, llvm_function, bit_cast_maker, + entry_instruction_finder, error_stream)) + return false; + } break; + case Instruction::GetElementPtr: { + // GetElementPtrConstantExpr + // OperandList[0] is base + // OperandList[1]... are indices + + FunctionValueCache get_element_pointer_maker( + [&value_maker, &entry_instruction_finder, old_constant, + constant_expr](llvm::Function *function) -> llvm::Value * { + Value *ptr = constant_expr->getOperand(0); + + if (ptr == old_constant) + ptr = value_maker.GetValue(function); + + std::vector<Value *> index_vector; + + unsigned operand_index; + unsigned num_operands = constant_expr->getNumOperands(); + + for (operand_index = 1; operand_index < num_operands; + ++operand_index) { + Value *operand = constant_expr->getOperand(operand_index); + + if (operand == old_constant) + operand = value_maker.GetValue(function); + + index_vector.push_back(operand); } - } - else - { - error_stream.Printf("error [IRForTarget internal]: Unhandled constant type: \"%s\"", PrintValue(constant).c_str()); - return false; - } + + ArrayRef<Value *> indices(index_vector); + + return GetElementPtrInst::Create( + nullptr, ptr, indices, "", + llvm::cast<Instruction>( + entry_instruction_finder.GetValue(function))); + }); + + if (!UnfoldConstant(constant_expr, llvm_function, + get_element_pointer_maker, + entry_instruction_finder, error_stream)) + return false; + } break; } - else - { - if (Instruction *inst = llvm::dyn_cast<Instruction>(user)) - { - if (llvm_function && inst->getParent()->getParent() != llvm_function) - { - error_stream.PutCString("error: Capturing non-local variables in expressions is unsupported.\n"); - return false; - } - inst->replaceUsesOfWith(old_constant, value_maker.GetValue(inst->getParent()->getParent())); - } - else - { - error_stream.Printf("error [IRForTarget internal]: Unhandled non-constant type: \"%s\"", PrintValue(user).c_str()); - return false; - } + } else { + error_stream.Printf( + "error [IRForTarget internal]: Unhandled constant type: \"%s\"", + PrintValue(constant).c_str()); + return false; + } + } else { + if (Instruction *inst = llvm::dyn_cast<Instruction>(user)) { + if (llvm_function && inst->getParent()->getParent() != llvm_function) { + error_stream.PutCString("error: Capturing non-local variables in " + "expressions is unsupported.\n"); + return false; } + inst->replaceUsesOfWith( + old_constant, value_maker.GetValue(inst->getParent()->getParent())); + } else { + error_stream.Printf( + "error [IRForTarget internal]: Unhandled non-constant type: \"%s\"", + PrintValue(user).c_str()); + return false; + } } + } - if (!isa<GlobalValue>(old_constant)) - { - old_constant->destroyConstant(); - } + if (!isa<GlobalValue>(old_constant)) { + old_constant->destroyConstant(); + } - return true; + return true; } -bool -IRForTarget::ReplaceVariables (Function &llvm_function) -{ - if (!m_resolve_vars) - return true; - - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool IRForTarget::ReplaceVariables(Function &llvm_function) { + if (!m_resolve_vars) + return true; - m_decl_map->DoStructLayout(); + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("Element arrangement:"); + m_decl_map->DoStructLayout(); - uint32_t num_elements; - uint32_t element_index; + if (log) + log->Printf("Element arrangement:"); - size_t size; - lldb::offset_t alignment; + uint32_t num_elements; + uint32_t element_index; - if (!m_decl_map->GetStructInfo (num_elements, size, alignment)) - return false; + size_t size; + lldb::offset_t alignment; - Function::arg_iterator iter(llvm_function.getArgumentList().begin()); + if (!m_decl_map->GetStructInfo(num_elements, size, alignment)) + return false; - if (iter == llvm_function.getArgumentList().end()) - { - m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes no arguments (should take at least a struct pointer)"); + Function::arg_iterator iter(llvm_function.getArgumentList().begin()); - return false; - } + if (iter == llvm_function.getArgumentList().end()) { + m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes no " + "arguments (should take at least a struct pointer)"); - Argument *argument = &*iter; + return false; + } - if (argument->getName().equals("this")) - { - ++iter; + Argument *argument = &*iter; - if (iter == llvm_function.getArgumentList().end()) - { - m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only 'this' argument (should take a struct pointer too)"); + if (argument->getName().equals("this")) { + ++iter; - return false; - } + if (iter == llvm_function.getArgumentList().end()) { + m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only " + "'this' argument (should take a struct pointer " + "too)"); - argument = &*iter; + return false; } - else if (argument->getName().equals("self")) - { - ++iter; - if (iter == llvm_function.getArgumentList().end()) - { - m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only 'self' argument (should take '_cmd' and a struct pointer too)"); + argument = &*iter; + } else if (argument->getName().equals("self")) { + ++iter; - return false; - } + if (iter == llvm_function.getArgumentList().end()) { + m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only " + "'self' argument (should take '_cmd' and a struct " + "pointer too)"); - if (!iter->getName().equals("_cmd")) - { - m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes '%s' after 'self' argument (should take '_cmd')", iter->getName().str().c_str()); + return false; + } - return false; - } + if (!iter->getName().equals("_cmd")) { + m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes '%s' " + "after 'self' argument (should take '_cmd')", + iter->getName().str().c_str()); - ++iter; + return false; + } - if (iter == llvm_function.getArgumentList().end()) - { - m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only 'self' and '_cmd' arguments (should take a struct pointer too)"); + ++iter; - return false; - } + if (iter == llvm_function.getArgumentList().end()) { + m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only " + "'self' and '_cmd' arguments (should take a struct " + "pointer too)"); - argument = &*iter; + return false; } - if (!argument->getName().equals("$__lldb_arg")) - { - m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes an argument named '%s' instead of the struct pointer", argument->getName().str().c_str()); - - return false; - } + argument = &*iter; + } - if (log) - log->Printf("Arg: \"%s\"", PrintValue(argument).c_str()); + if (!argument->getName().equals("$__lldb_arg")) { + m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes an " + "argument named '%s' instead of the struct pointer", + argument->getName().str().c_str()); - BasicBlock &entry_block(llvm_function.getEntryBlock()); - Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg()); + return false; + } - if (!FirstEntryInstruction) - { - m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find the first instruction in the wrapper for use in rewriting"); + if (log) + log->Printf("Arg: \"%s\"", PrintValue(argument).c_str()); - return false; - } + BasicBlock &entry_block(llvm_function.getEntryBlock()); + Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg()); - LLVMContext &context(m_module->getContext()); - IntegerType *offset_type(Type::getInt32Ty(context)); + if (!FirstEntryInstruction) { + m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find the " + "first instruction in the wrapper for use in " + "rewriting"); - if (!offset_type) - { - m_error_stream.Printf("Internal error [IRForTarget]: Couldn't produce an offset type"); + return false; + } - return false; - } + LLVMContext &context(m_module->getContext()); + IntegerType *offset_type(Type::getInt32Ty(context)); - for (element_index = 0; element_index < num_elements; ++element_index) - { - const clang::NamedDecl *decl = NULL; - Value *value = NULL; - lldb::offset_t offset; - lldb_private::ConstString name; + if (!offset_type) { + m_error_stream.Printf( + "Internal error [IRForTarget]: Couldn't produce an offset type"); - if (!m_decl_map->GetStructElement (decl, value, offset, name, element_index)) - { - m_error_stream.Printf("Internal error [IRForTarget]: Structure information is incomplete"); + return false; + } - return false; - } + for (element_index = 0; element_index < num_elements; ++element_index) { + const clang::NamedDecl *decl = NULL; + Value *value = NULL; + lldb::offset_t offset; + lldb_private::ConstString name; - if (log) - log->Printf(" \"%s\" (\"%s\") placed at %" PRIu64, - name.GetCString(), - decl->getNameAsString().c_str(), - offset); - - if (value) - { - if (log) - log->Printf(" Replacing [%s]", PrintValue(value).c_str()); - - FunctionValueCache body_result_maker ([this, name, offset_type, offset, argument, value] (llvm::Function *function)->llvm::Value * { - // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result - // variable is an rvalue, we have to synthesize a dereference of the appropriate structure - // entry in order to produce the static variable that the AST thinks it is accessing. - - llvm::Instruction *entry_instruction = llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function)); - - ConstantInt *offset_int(ConstantInt::get(offset_type, offset, true)); - GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(nullptr, - argument, - offset_int, - "", - entry_instruction); - - if (name == m_result_name && !m_result_is_pointer) - { - BitCastInst *bit_cast = new BitCastInst(get_element_ptr, - value->getType()->getPointerTo(), - "", - entry_instruction); - - LoadInst *load = new LoadInst(bit_cast, "", entry_instruction); - - return load; - } - else - { - BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", entry_instruction); + if (!m_decl_map->GetStructElement(decl, value, offset, name, + element_index)) { + m_error_stream.Printf( + "Internal error [IRForTarget]: Structure information is incomplete"); - return bit_cast; - } - }); + return false; + } - if (Constant *constant = dyn_cast<Constant>(value)) - { - if (!UnfoldConstant(constant, &llvm_function, body_result_maker, m_entry_instruction_finder, m_error_stream)) - { - return false; - } - } - else if (Instruction *instruction = dyn_cast<Instruction>(value)) - { - if (instruction->getParent()->getParent() != &llvm_function) - { - m_error_stream.PutCString("error: Capturing non-local variables in expressions is unsupported.\n"); - return false; - } - value->replaceAllUsesWith(body_result_maker.GetValue(instruction->getParent()->getParent())); - } - else - { - if (log) - log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(value).c_str()); - return false; + if (log) + log->Printf(" \"%s\" (\"%s\") placed at %" PRIu64, name.GetCString(), + decl->getNameAsString().c_str(), offset); + + if (value) { + if (log) + log->Printf(" Replacing [%s]", PrintValue(value).c_str()); + + FunctionValueCache body_result_maker( + [this, name, offset_type, offset, argument, + value](llvm::Function *function) -> llvm::Value * { + // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in + // cases where the result + // variable is an rvalue, we have to synthesize a dereference of the + // appropriate structure + // entry in order to produce the static variable that the AST thinks + // it is accessing. + + llvm::Instruction *entry_instruction = llvm::cast<Instruction>( + m_entry_instruction_finder.GetValue(function)); + + ConstantInt *offset_int( + ConstantInt::get(offset_type, offset, true)); + GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create( + nullptr, argument, offset_int, "", entry_instruction); + + if (name == m_result_name && !m_result_is_pointer) { + BitCastInst *bit_cast = new BitCastInst( + get_element_ptr, value->getType()->getPointerTo(), "", + entry_instruction); + + LoadInst *load = new LoadInst(bit_cast, "", entry_instruction); + + return load; + } else { + BitCastInst *bit_cast = new BitCastInst( + get_element_ptr, value->getType(), "", entry_instruction); + + return bit_cast; } + }); - if (GlobalVariable *var = dyn_cast<GlobalVariable>(value)) - var->eraseFromParent(); + if (Constant *constant = dyn_cast<Constant>(value)) { + if (!UnfoldConstant(constant, &llvm_function, body_result_maker, + m_entry_instruction_finder, m_error_stream)) { + return false; } + } else if (Instruction *instruction = dyn_cast<Instruction>(value)) { + if (instruction->getParent()->getParent() != &llvm_function) { + m_error_stream.PutCString("error: Capturing non-local variables in " + "expressions is unsupported.\n"); + return false; + } + value->replaceAllUsesWith( + body_result_maker.GetValue(instruction->getParent()->getParent())); + } else { + if (log) + log->Printf("Unhandled non-constant type: \"%s\"", + PrintValue(value).c_str()); + return false; + } + + if (GlobalVariable *var = dyn_cast<GlobalVariable>(value)) + var->eraseFromParent(); } + } - if (log) - log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", (int64_t)alignment, (uint64_t)size); + if (log) + log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", + (int64_t)alignment, (uint64_t)size); - return true; + return true; } -llvm::Constant * -IRForTarget::BuildRelocation(llvm::Type *type, uint64_t offset) -{ - llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset); +llvm::Constant *IRForTarget::BuildRelocation(llvm::Type *type, + uint64_t offset) { + llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset); - llvm::Constant *offset_array[1]; + llvm::Constant *offset_array[1]; - offset_array[0] = offset_int; + offset_array[0] = offset_int; - llvm::ArrayRef<llvm::Constant *> offsets(offset_array, 1); - llvm::Type *char_type = llvm::Type::getInt8Ty(m_module->getContext()); - llvm::Type *char_pointer_type = char_type->getPointerTo(); + llvm::ArrayRef<llvm::Constant *> offsets(offset_array, 1); + llvm::Type *char_type = llvm::Type::getInt8Ty(m_module->getContext()); + llvm::Type *char_pointer_type = char_type->getPointerTo(); - llvm::Constant *reloc_placeholder_bitcast = ConstantExpr::getBitCast(m_reloc_placeholder, char_pointer_type); - llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr(char_type, reloc_placeholder_bitcast, offsets); - llvm::Constant *reloc_bitcast = ConstantExpr::getBitCast(reloc_getelementptr, type); + llvm::Constant *reloc_placeholder_bitcast = + ConstantExpr::getBitCast(m_reloc_placeholder, char_pointer_type); + llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr( + char_type, reloc_placeholder_bitcast, offsets); + llvm::Constant *reloc_bitcast = + ConstantExpr::getBitCast(reloc_getelementptr, type); - return reloc_bitcast; + return reloc_bitcast; } -bool -IRForTarget::runOnModule (Module &llvm_module) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +bool IRForTarget::runOnModule(Module &llvm_module) { + lldb_private::Log *log( + lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - m_module = &llvm_module; - m_target_data.reset(new DataLayout(m_module)); - m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), m_target_data->getPointerSizeInBits()); + m_module = &llvm_module; + m_target_data.reset(new DataLayout(m_module)); + m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), + m_target_data->getPointerSizeInBits()); - if (log) - { - std::string s; - raw_string_ostream oss(s); + if (log) { + std::string s; + raw_string_ostream oss(s); - m_module->print(oss, NULL); + m_module->print(oss, NULL); - oss.flush(); + oss.flush(); - log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str()); - } + log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str()); + } - Function *const main_function = m_func_name.IsEmpty() ? nullptr : m_module->getFunction(m_func_name.GetStringRef()); + Function *const main_function = + m_func_name.IsEmpty() ? nullptr + : m_module->getFunction(m_func_name.GetStringRef()); - if (!m_func_name.IsEmpty() && !main_function) - { - if (log) - log->Printf("Couldn't find \"%s()\" in the module", m_func_name.AsCString()); + if (!m_func_name.IsEmpty() && !main_function) { + if (log) + log->Printf("Couldn't find \"%s()\" in the module", + m_func_name.AsCString()); - m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", - m_func_name.AsCString()); + m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find wrapper " + "'%s' in the module", + m_func_name.AsCString()); - return false; - } + return false; + } - if (main_function) - { - if (!FixFunctionLinkage(*main_function)) - { - if (log) - log->Printf("Couldn't fix the linkage for the function"); + if (main_function) { + if (!FixFunctionLinkage(*main_function)) { + if (log) + log->Printf("Couldn't fix the linkage for the function"); - return false; - } + return false; } + } - llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext()); + llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext()); - m_reloc_placeholder = new llvm::GlobalVariable((*m_module), - int8_ty, - false /* IsConstant */, - GlobalVariable::InternalLinkage, - Constant::getNullValue(int8_ty), - "reloc_placeholder", - NULL /* InsertBefore */, - GlobalVariable::NotThreadLocal /* ThreadLocal */, - 0 /* AddressSpace */); + m_reloc_placeholder = new llvm::GlobalVariable( + (*m_module), int8_ty, false /* IsConstant */, + GlobalVariable::InternalLinkage, Constant::getNullValue(int8_ty), + "reloc_placeholder", NULL /* InsertBefore */, + GlobalVariable::NotThreadLocal /* ThreadLocal */, 0 /* AddressSpace */); - //////////////////////////////////////////////////////////// - // Replace $__lldb_expr_result with a persistent variable - // + //////////////////////////////////////////////////////////// + // Replace $__lldb_expr_result with a persistent variable + // - if (main_function) - { - if (!CreateResultVariable(*main_function)) - { - if (log) - log->Printf("CreateResultVariable() failed"); + if (main_function) { + if (!CreateResultVariable(*main_function)) { + if (log) + log->Printf("CreateResultVariable() failed"); - // CreateResultVariable() reports its own errors, so we don't do so here + // CreateResultVariable() reports its own errors, so we don't do so here - return false; - } + return false; } + } - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream oss(s); + if (log && log->GetVerbose()) { + std::string s; + raw_string_ostream oss(s); - m_module->print(oss, NULL); + m_module->print(oss, NULL); - oss.flush(); + oss.flush(); - log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str()); - } + log->Printf("Module after creating the result variable: \n\"%s\"", + s.c_str()); + } - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); - fi != fe; - ++fi) - { - llvm::Function *function = &*fi; + for (Module::iterator fi = m_module->begin(), fe = m_module->end(); fi != fe; + ++fi) { + llvm::Function *function = &*fi; - if (function->begin() == function->end()) - continue; + if (function->begin() == function->end()) + continue; - Function::iterator bbi; + Function::iterator bbi; - for (bbi = function->begin(); - bbi != function->end(); - ++bbi) - { - if (!RemoveGuards(*bbi)) - { - if (log) - log->Printf("RemoveGuards() failed"); + for (bbi = function->begin(); bbi != function->end(); ++bbi) { + if (!RemoveGuards(*bbi)) { + if (log) + log->Printf("RemoveGuards() failed"); - // RemoveGuards() reports its own errors, so we don't do so here + // RemoveGuards() reports its own errors, so we don't do so here - return false; - } + return false; + } - if (!RewritePersistentAllocs(*bbi)) - { - if (log) - log->Printf("RewritePersistentAllocs() failed"); + if (!RewritePersistentAllocs(*bbi)) { + if (log) + log->Printf("RewritePersistentAllocs() failed"); - // RewritePersistentAllocs() reports its own errors, so we don't do so here + // RewritePersistentAllocs() reports its own errors, so we don't do so + // here - return false; - } + return false; + } - if (!RemoveCXAAtExit(*bbi)) - { - if (log) - log->Printf("RemoveCXAAtExit() failed"); + if (!RemoveCXAAtExit(*bbi)) { + if (log) + log->Printf("RemoveCXAAtExit() failed"); - // RemoveCXAAtExit() reports its own errors, so we don't do so here + // RemoveCXAAtExit() reports its own errors, so we don't do so here - return false; - } - } + return false; + } } + } - /////////////////////////////////////////////////////////////////////////////// - // Fix all Objective-C constant strings to use NSStringWithCString:encoding: - // + /////////////////////////////////////////////////////////////////////////////// + // Fix all Objective-C constant strings to use NSStringWithCString:encoding: + // - if (!RewriteObjCConstStrings()) - { - if (log) - log->Printf("RewriteObjCConstStrings() failed"); + if (!RewriteObjCConstStrings()) { + if (log) + log->Printf("RewriteObjCConstStrings() failed"); - // RewriteObjCConstStrings() reports its own errors, so we don't do so here + // RewriteObjCConstStrings() reports its own errors, so we don't do so here - return false; - } + return false; + } - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); - fi != fe; - ++fi) - { - llvm::Function *function = &*fi; + for (Module::iterator fi = m_module->begin(), fe = m_module->end(); fi != fe; + ++fi) { + llvm::Function *function = &*fi; - for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); - bbi != bbe; - ++bbi) - { - if (!RewriteObjCSelectors(*bbi)) - { - if (log) - log->Printf("RewriteObjCSelectors() failed"); + for (llvm::Function::iterator bbi = function->begin(), + bbe = function->end(); + bbi != bbe; ++bbi) { + if (!RewriteObjCSelectors(*bbi)) { + if (log) + log->Printf("RewriteObjCSelectors() failed"); - // RewriteObjCSelectors() reports its own errors, so we don't do so here + // RewriteObjCSelectors() reports its own errors, so we don't do so here - return false; - } - } + return false; + } } + } - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); - fi != fe; - ++fi) - { - llvm::Function *function = &*fi; + for (Module::iterator fi = m_module->begin(), fe = m_module->end(); fi != fe; + ++fi) { + llvm::Function *function = &*fi; - for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); - bbi != bbe; - ++bbi) - { - if (!ResolveCalls(*bbi)) - { - if (log) - log->Printf("ResolveCalls() failed"); + for (llvm::Function::iterator bbi = function->begin(), + bbe = function->end(); + bbi != bbe; ++bbi) { + if (!ResolveCalls(*bbi)) { + if (log) + log->Printf("ResolveCalls() failed"); - // ResolveCalls() reports its own errors, so we don't do so here + // ResolveCalls() reports its own errors, so we don't do so here - return false; - } - } + return false; + } } + } - //////////////////////////////////////////////////////////////////////// - // Run function-level passes that only make sense on the main function - // + //////////////////////////////////////////////////////////////////////// + // Run function-level passes that only make sense on the main function + // - if (main_function) - { - if (!ResolveExternals(*main_function)) - { - if (log) - log->Printf("ResolveExternals() failed"); + if (main_function) { + if (!ResolveExternals(*main_function)) { + if (log) + log->Printf("ResolveExternals() failed"); - // ResolveExternals() reports its own errors, so we don't do so here + // ResolveExternals() reports its own errors, so we don't do so here - return false; - } + return false; + } - if (!ReplaceVariables(*main_function)) - { - if (log) - log->Printf("ReplaceVariables() failed"); + if (!ReplaceVariables(*main_function)) { + if (log) + log->Printf("ReplaceVariables() failed"); - // ReplaceVariables() reports its own errors, so we don't do so here + // ReplaceVariables() reports its own errors, so we don't do so here - return false; - } + return false; } + } - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream oss(s); + if (log && log->GetVerbose()) { + std::string s; + raw_string_ostream oss(s); - m_module->print(oss, NULL); + m_module->print(oss, NULL); - oss.flush(); + oss.flush(); - log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str()); - } + log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str()); + } - return true; + return true; } -void -IRForTarget::assignPassManager (PMStack &pass_mgr_stack, PassManagerType pass_mgr_type) -{ -} +void IRForTarget::assignPassManager(PMStack &pass_mgr_stack, + PassManagerType pass_mgr_type) {} -PassManagerType -IRForTarget::getPotentialPassManagerType() const -{ - return PMT_ModulePassManager; +PassManagerType IRForTarget::getPotentialPassManagerType() const { + return PMT_ModulePassManager; } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h index 39d5159acf9..fecb32f685c 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -1,4 +1,5 @@ -//===-- IRForTarget.h ---------------------------------------------*- C++ -*-===// +//===-- IRForTarget.h ---------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,38 +11,38 @@ #ifndef liblldb_IRForTarget_h_ #define liblldb_IRForTarget_h_ -#include "lldb/lldb-public.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamString.h" #include "lldb/Symbol/TaggedASTType.h" +#include "lldb/lldb-public.h" #include "llvm/Pass.h" -#include <map> #include <functional> +#include <map> namespace llvm { - class BasicBlock; - class CallInst; - class Constant; - class ConstantInt; - class Function; - class GlobalValue; - class GlobalVariable; - class Instruction; - class IntegerType; - class Module; - class StoreInst; - class DataLayout; - class Type; - class Value; +class BasicBlock; +class CallInst; +class Constant; +class ConstantInt; +class Function; +class GlobalValue; +class GlobalVariable; +class Instruction; +class IntegerType; +class Module; +class StoreInst; +class DataLayout; +class Type; +class Value; } namespace lldb_private { - class ClangExpressionDeclMap; - class IRExecutionUnit; - class IRMemoryMap; +class ClangExpressionDeclMap; +class IRExecutionUnit; +class IRMemoryMap; } //---------------------------------------------------------------------- @@ -58,596 +59,578 @@ namespace lldb_private { /// transformations are discussed in more detail next to their relevant /// functions. //---------------------------------------------------------------------- -class IRForTarget : public llvm::ModulePass -{ +class IRForTarget : public llvm::ModulePass { public: - enum class LookupResult { - Success, - Fail, - Ignore - }; - - //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] decl_map - /// The list of externally-referenced variables for the expression, - /// for use in looking up globals and allocating the argument - /// struct. See the documentation for ClangExpressionDeclMap. - /// - /// @param[in] resolve_vars - /// True if the external variable references (including persistent - /// variables) should be resolved. If not, only external functions - /// are resolved. - /// - /// @param[in] execution_policy - /// Determines whether an IR interpreter can be used to statically - /// evaluate the expression. - /// - /// @param[in] const_result - /// This variable is populated with the statically-computed result - /// of the function, if it has no side-effects and the result can - /// be computed statically. - /// - /// @param[in] execution_unit - /// The holder for raw data associated with the expression. - /// - /// @param[in] error_stream - /// If non-NULL, a stream on which errors can be printed. - /// - /// @param[in] func_name - /// The name of the function to prepare for execution in the target. - //------------------------------------------------------------------ - IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, - bool resolve_vars, - lldb_private::IRExecutionUnit &execution_unit, - lldb_private::Stream &error_stream, - const char* func_name = "$__lldb_expr"); - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - ~IRForTarget() override; - - //------------------------------------------------------------------ - /// Run this IR transformer on a single module - /// - /// Implementation of the llvm::ModulePass::runOnModule() function. - /// - /// @param[in] llvm_module - /// The module to run on. This module is searched for the function - /// $__lldb_expr, and that function is passed to the passes one by - /// one. - /// - /// @param[in] interpreter_error - /// An error. If the expression fails to be interpreted, this error - /// is set to a reason why. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - runOnModule(llvm::Module &llvm_module) override; - - //------------------------------------------------------------------ - /// Interface stub - /// - /// Implementation of the llvm::ModulePass::assignPassManager() - /// function. - //------------------------------------------------------------------ - void - assignPassManager(llvm::PMStack &pass_mgr_stack, - llvm::PassManagerType pass_mgr_type = llvm::PMT_ModulePassManager) override; - - //------------------------------------------------------------------ - /// Returns PMT_ModulePassManager - /// - /// Implementation of the llvm::ModulePass::getPotentialPassManagerType() - /// function. - //------------------------------------------------------------------ - llvm::PassManagerType - getPotentialPassManagerType() const override; + enum class LookupResult { Success, Fail, Ignore }; + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] decl_map + /// The list of externally-referenced variables for the expression, + /// for use in looking up globals and allocating the argument + /// struct. See the documentation for ClangExpressionDeclMap. + /// + /// @param[in] resolve_vars + /// True if the external variable references (including persistent + /// variables) should be resolved. If not, only external functions + /// are resolved. + /// + /// @param[in] execution_policy + /// Determines whether an IR interpreter can be used to statically + /// evaluate the expression. + /// + /// @param[in] const_result + /// This variable is populated with the statically-computed result + /// of the function, if it has no side-effects and the result can + /// be computed statically. + /// + /// @param[in] execution_unit + /// The holder for raw data associated with the expression. + /// + /// @param[in] error_stream + /// If non-NULL, a stream on which errors can be printed. + /// + /// @param[in] func_name + /// The name of the function to prepare for execution in the target. + //------------------------------------------------------------------ + IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, bool resolve_vars, + lldb_private::IRExecutionUnit &execution_unit, + lldb_private::Stream &error_stream, + const char *func_name = "$__lldb_expr"); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~IRForTarget() override; + + //------------------------------------------------------------------ + /// Run this IR transformer on a single module + /// + /// Implementation of the llvm::ModulePass::runOnModule() function. + /// + /// @param[in] llvm_module + /// The module to run on. This module is searched for the function + /// $__lldb_expr, and that function is passed to the passes one by + /// one. + /// + /// @param[in] interpreter_error + /// An error. If the expression fails to be interpreted, this error + /// is set to a reason why. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool runOnModule(llvm::Module &llvm_module) override; + + //------------------------------------------------------------------ + /// Interface stub + /// + /// Implementation of the llvm::ModulePass::assignPassManager() + /// function. + //------------------------------------------------------------------ + void assignPassManager(llvm::PMStack &pass_mgr_stack, + llvm::PassManagerType pass_mgr_type = + llvm::PMT_ModulePassManager) override; + + //------------------------------------------------------------------ + /// Returns PMT_ModulePassManager + /// + /// Implementation of the llvm::ModulePass::getPotentialPassManagerType() + /// function. + //------------------------------------------------------------------ + llvm::PassManagerType getPotentialPassManagerType() const override; private: - //------------------------------------------------------------------ - /// Ensures that the current function's linkage is set to external. - /// Otherwise the JIT may not return an address for it. - /// - /// @param[in] llvm_function - /// The function whose linkage is to be fixed. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - FixFunctionLinkage (llvm::Function &llvm_function); - - //------------------------------------------------------------------ - /// A module-level pass to replace all function pointers with their - /// integer equivalents. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] llvm_module - /// The module currently being processed. - /// - /// @param[in] llvm_function - /// The function currently being processed. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - HasSideEffects (llvm::Function &llvm_function); - - //------------------------------------------------------------------ - /// A function-level pass to check whether the function has side - /// effects. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Get the address of a function, and a location to put the complete - /// Value of the function if one is available. - /// - /// @param[in] function - /// The function to find the location of. - /// - /// @param[out] ptr - /// The location of the function in the target. - /// - /// @param[out] name - /// The resolved name of the function (matters for intrinsics). - /// - /// @param[out] value_ptr - /// A variable to put the function's completed Value* in, or NULL - /// if the Value* shouldn't be stored anywhere. - /// - /// @return - /// The pointer. - //------------------------------------------------------------------ - LookupResult - GetFunctionAddress (llvm::Function *function, - uint64_t &ptr, - lldb_private::ConstString &name, - llvm::Constant **&value_ptr); - - //------------------------------------------------------------------ - /// A function-level pass to take the generated global value - /// $__lldb_expr_result and make it into a persistent variable. - /// Also see ASTResultSynthesizer. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Find the NamedDecl corresponding to a Value. This interface is - /// exposed for the IR interpreter. - /// - /// @param[in] module - /// The module containing metadata to search - /// - /// @param[in] global - /// The global entity to search for - /// - /// @return - /// The corresponding variable declaration - //------------------------------------------------------------------ + //------------------------------------------------------------------ + /// Ensures that the current function's linkage is set to external. + /// Otherwise the JIT may not return an address for it. + /// + /// @param[in] llvm_function + /// The function whose linkage is to be fixed. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool FixFunctionLinkage(llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to replace all function pointers with their + /// integer equivalents. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_module + /// The module currently being processed. + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool HasSideEffects(llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A function-level pass to check whether the function has side + /// effects. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Get the address of a function, and a location to put the complete + /// Value of the function if one is available. + /// + /// @param[in] function + /// The function to find the location of. + /// + /// @param[out] ptr + /// The location of the function in the target. + /// + /// @param[out] name + /// The resolved name of the function (matters for intrinsics). + /// + /// @param[out] value_ptr + /// A variable to put the function's completed Value* in, or NULL + /// if the Value* shouldn't be stored anywhere. + /// + /// @return + /// The pointer. + //------------------------------------------------------------------ + LookupResult GetFunctionAddress(llvm::Function *function, uint64_t &ptr, + lldb_private::ConstString &name, + llvm::Constant **&value_ptr); + + //------------------------------------------------------------------ + /// A function-level pass to take the generated global value + /// $__lldb_expr_result and make it into a persistent variable. + /// Also see ASTResultSynthesizer. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Find the NamedDecl corresponding to a Value. This interface is + /// exposed for the IR interpreter. + /// + /// @param[in] module + /// The module containing metadata to search + /// + /// @param[in] global + /// The global entity to search for + /// + /// @return + /// The corresponding variable declaration + //------------------------------------------------------------------ public: - static clang::NamedDecl * - DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module); + static clang::NamedDecl *DeclForGlobal(const llvm::GlobalValue *global_val, + llvm::Module *module); + private: - clang::NamedDecl * - DeclForGlobal (llvm::GlobalValue *global); - - //------------------------------------------------------------------ - /// Set the constant result variable m_const_result to the provided - /// constant, assuming it can be evaluated. The result variable - /// will be reset to NULL later if the expression has side effects. - /// - /// @param[in] initializer - /// The constant initializer for the variable. - /// - /// @param[in] name - /// The name of the result variable. - /// - /// @param[in] type - /// The Clang type of the result variable. - //------------------------------------------------------------------ - void - MaybeSetConstantResult (llvm::Constant *initializer, - const lldb_private::ConstString &name, - lldb_private::TypeFromParser type); - - //------------------------------------------------------------------ - /// If the IR represents a cast of a variable, set m_const_result - /// to the result of the cast. The result variable will be reset to - /// NULL latger if the expression has side effects. - /// - /// @param[in] type - /// The Clang type of the result variable. - //------------------------------------------------------------------ - void - MaybeSetCastResult (lldb_private::TypeFromParser type); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] llvm_function - /// The function currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - CreateResultVariable (llvm::Function &llvm_function); - - //------------------------------------------------------------------ - /// A module-level pass to find Objective-C constant strings and - /// transform them to calls to CFStringCreateWithBytes. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Rewrite a single Objective-C constant string. - /// - /// @param[in] NSStr - /// The constant NSString to be transformed - /// - /// @param[in] CStr - /// The constant C string inside the NSString. This will be - /// passed as the bytes argument to CFStringCreateWithBytes. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RewriteObjCConstString (llvm::GlobalVariable *NSStr, - llvm::GlobalVariable *CStr); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RewriteObjCConstStrings (); - - //------------------------------------------------------------------ - /// A basic block-level pass to find all Objective-C method calls and - /// rewrite them to use sel_registerName instead of statically allocated - /// selectors. The reason is that the selectors are created on the - /// assumption that the Objective-C runtime will scan the appropriate - /// section and prepare them. This doesn't happen when code is copied - /// into the target, though, and there's no easy way to induce the - /// runtime to scan them. So instead we get our selectors from - /// sel_registerName. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Replace a single selector reference - /// - /// @param[in] selector_load - /// The load of the statically-allocated selector. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RewriteObjCSelector (llvm::Instruction* selector_load); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] basic_block - /// The basic block currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RewriteObjCSelectors (llvm::BasicBlock &basic_block); - - //------------------------------------------------------------------ - /// A basic block-level pass to find all newly-declared persistent - /// variables and register them with the ClangExprDeclMap. This - /// allows them to be materialized and dematerialized like normal - /// external variables. Before transformation, these persistent - /// variables look like normal locals, so they have an allocation. - /// This pass excises these allocations and makes references look - /// like external references where they will be resolved -- like all - /// other external references -- by ResolveExternals(). - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Handle a single allocation of a persistent variable - /// - /// @param[in] persistent_alloc - /// The allocation of the persistent variable. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RewritePersistentAlloc (llvm::Instruction *persistent_alloc); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] basic_block - /// The basic block currently being processed. - //------------------------------------------------------------------ - bool - RewritePersistentAllocs (llvm::BasicBlock &basic_block); - - //------------------------------------------------------------------ - /// A function-level pass to find all external variables and functions - /// used in the IR. Each found external variable is added to the - /// struct, and each external function is resolved in place, its call - /// replaced with a call to a function pointer whose value is the - /// address of the function in the target process. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Write an initializer to a memory array of assumed sufficient - /// size. - /// - /// @param[in] data - /// A pointer to the data to write to. - /// - /// @param[in] initializer - /// The initializer itself. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - MaterializeInitializer (uint8_t *data, llvm::Constant *initializer); - - //------------------------------------------------------------------ - /// Move an internal variable into the static allocation section. - /// - /// @param[in] global_variable - /// The variable. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - MaterializeInternalVariable (llvm::GlobalVariable *global_variable); - - //------------------------------------------------------------------ - /// Handle a single externally-defined variable - /// - /// @param[in] value - /// The variable. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - MaybeHandleVariable (llvm::Value *value); - - //------------------------------------------------------------------ - /// Handle a single externally-defined symbol - /// - /// @param[in] symbol - /// The symbol. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - HandleSymbol (llvm::Value *symbol); - - //------------------------------------------------------------------ - /// Handle a single externally-defined Objective-C class - /// - /// @param[in] classlist_reference - /// The reference, usually "01L_OBJC_CLASSLIST_REFERENCES_$_n" - /// where n (if present) is an index. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - HandleObjCClass(llvm::Value *classlist_reference); - - //------------------------------------------------------------------ - /// Handle all the arguments to a function call - /// - /// @param[in] C - /// The call instruction. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - MaybeHandleCallArguments (llvm::CallInst *call_inst); - - //------------------------------------------------------------------ - /// Resolve variable references in calls to external functions - /// - /// @param[in] basic_block - /// The basic block currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - ResolveCalls (llvm::BasicBlock &basic_block); - - //------------------------------------------------------------------ - /// Remove calls to __cxa_atexit, which should never be generated by - /// expressions. - /// - /// @param[in] call_inst - /// The call instruction. - /// - /// @return - /// True if the scan was successful; false if some operation - /// failed - //------------------------------------------------------------------ - bool - RemoveCXAAtExit (llvm::BasicBlock &basic_block); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] basic_block - /// The function currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - ResolveExternals (llvm::Function &llvm_function); - - //------------------------------------------------------------------ - /// A basic block-level pass to excise guard variables from the code. - /// The result for the function is passed through Clang as a static - /// variable. Static variables normally have guard variables to - /// ensure that they are only initialized once. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Rewrite a load to a guard variable to return constant 0. - /// - /// @param[in] guard_load - /// The load instruction to zero out. - //------------------------------------------------------------------ - void - TurnGuardLoadIntoZero(llvm::Instruction* guard_load); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] basic_block - /// The basic block currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RemoveGuards (llvm::BasicBlock &basic_block); - - //------------------------------------------------------------------ - /// A function-level pass to make all external variable references - /// point at the correct offsets from the void* passed into the - /// function. ClangExpressionDeclMap::DoStructLayout() must be called - /// beforehand, so that the offsets are valid. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] llvm_function - /// The function currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - ReplaceVariables(llvm::Function &llvm_function); - - /// Flags - bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved - lldb_private::ConstString m_func_name; ///< The name of the function to translate - lldb_private::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...) - lldb_private::TypeFromParser m_result_type; ///< The type of the result variable. - llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet. - std::unique_ptr<llvm::DataLayout> - m_target_data; ///< The target data for the module being processed, or NULL if there is no module. - lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls - llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the - ///appropriate function pointer type - llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate - ///function pointer type - llvm::IntegerType *m_intptr_ty; ///< The type of an integer large enough to hold a pointer. - lldb_private::Stream &m_error_stream; ///< The stream on which errors should be printed - lldb_private::IRExecutionUnit &m_execution_unit; ///< The execution unit containing the IR being created. - - llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that writes to the result variable. If - ///m_has_side_effects is true, this is NULL. - bool m_result_is_pointer; ///< True if the function's result in the AST is a pointer (see comments in - ///ASTResultSynthesizer::SynthesizeBodyResult) - - llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be replaced by a pointer to the final - ///location of the static allocation. - - //------------------------------------------------------------------ - /// UnfoldConstant operates on a constant [Old] which has just been - /// replaced with a value [New]. We assume that new_value has - /// been properly placed early in the function, in front of the - /// first instruction in the entry basic block - /// [FirstEntryInstruction]. - /// - /// UnfoldConstant reads through the uses of Old and replaces Old - /// in those uses with New. Where those uses are constants, the - /// function generates new instructions to compute the result of the - /// new, non-constant expression and places them before - /// FirstEntryInstruction. These instructions replace the constant - /// uses, so UnfoldConstant calls itself recursively for those. - /// - /// @param[in] llvm_function - /// The function currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - - class FunctionValueCache { - public: - typedef std::function <llvm::Value *(llvm::Function *)> Maker; - - FunctionValueCache (Maker const &maker); - ~FunctionValueCache (); - llvm::Value *GetValue (llvm::Function *function); - private: - Maker const m_maker; - typedef std::map<llvm::Function *, llvm::Value *> FunctionValueMap; - FunctionValueMap m_values; - }; - - FunctionValueCache m_entry_instruction_finder; - - static bool - UnfoldConstant (llvm::Constant *old_constant, - llvm::Function *llvm_function, - FunctionValueCache &value_maker, - FunctionValueCache &entry_instruction_finder, - lldb_private::Stream &error_stream); - - //------------------------------------------------------------------ - /// Construct a reference to m_reloc_placeholder with a given type - /// and offset. This typically happens after inserting data into - /// m_data_allocator. - /// - /// @param[in] type - /// The type of the value being loaded. - /// - /// @param[in] offset - /// The offset of the value from the base of m_data_allocator. - /// - /// @return - /// The Constant for the reference, usually a ConstantExpr. - //------------------------------------------------------------------ - llvm::Constant * - BuildRelocation(llvm::Type *type, - uint64_t offset); - - //------------------------------------------------------------------ - /// Commit the allocation in m_data_allocator and use its final - /// location to replace m_reloc_placeholder. - /// - /// @param[in] module - /// The module that m_data_allocator resides in - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - CompleteDataAllocation (); + clang::NamedDecl *DeclForGlobal(llvm::GlobalValue *global); + + //------------------------------------------------------------------ + /// Set the constant result variable m_const_result to the provided + /// constant, assuming it can be evaluated. The result variable + /// will be reset to NULL later if the expression has side effects. + /// + /// @param[in] initializer + /// The constant initializer for the variable. + /// + /// @param[in] name + /// The name of the result variable. + /// + /// @param[in] type + /// The Clang type of the result variable. + //------------------------------------------------------------------ + void MaybeSetConstantResult(llvm::Constant *initializer, + const lldb_private::ConstString &name, + lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ + /// If the IR represents a cast of a variable, set m_const_result + /// to the result of the cast. The result variable will be reset to + /// NULL latger if the expression has side effects. + /// + /// @param[in] type + /// The Clang type of the result variable. + //------------------------------------------------------------------ + void MaybeSetCastResult(lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool CreateResultVariable(llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to find Objective-C constant strings and + /// transform them to calls to CFStringCreateWithBytes. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Rewrite a single Objective-C constant string. + /// + /// @param[in] NSStr + /// The constant NSString to be transformed + /// + /// @param[in] CStr + /// The constant C string inside the NSString. This will be + /// passed as the bytes argument to CFStringCreateWithBytes. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool RewriteObjCConstString(llvm::GlobalVariable *NSStr, + llvm::GlobalVariable *CStr); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool RewriteObjCConstStrings(); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all Objective-C method calls and + /// rewrite them to use sel_registerName instead of statically allocated + /// selectors. The reason is that the selectors are created on the + /// assumption that the Objective-C runtime will scan the appropriate + /// section and prepare them. This doesn't happen when code is copied + /// into the target, though, and there's no easy way to induce the + /// runtime to scan them. So instead we get our selectors from + /// sel_registerName. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Replace a single selector reference + /// + /// @param[in] selector_load + /// The load of the statically-allocated selector. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool RewriteObjCSelector(llvm::Instruction *selector_load); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool RewriteObjCSelectors(llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all newly-declared persistent + /// variables and register them with the ClangExprDeclMap. This + /// allows them to be materialized and dematerialized like normal + /// external variables. Before transformation, these persistent + /// variables look like normal locals, so they have an allocation. + /// This pass excises these allocations and makes references look + /// like external references where they will be resolved -- like all + /// other external references -- by ResolveExternals(). + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Handle a single allocation of a persistent variable + /// + /// @param[in] persistent_alloc + /// The allocation of the persistent variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool RewritePersistentAlloc(llvm::Instruction *persistent_alloc); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + //------------------------------------------------------------------ + bool RewritePersistentAllocs(llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A function-level pass to find all external variables and functions + /// used in the IR. Each found external variable is added to the + /// struct, and each external function is resolved in place, its call + /// replaced with a call to a function pointer whose value is the + /// address of the function in the target process. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Write an initializer to a memory array of assumed sufficient + /// size. + /// + /// @param[in] data + /// A pointer to the data to write to. + /// + /// @param[in] initializer + /// The initializer itself. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool MaterializeInitializer(uint8_t *data, llvm::Constant *initializer); + + //------------------------------------------------------------------ + /// Move an internal variable into the static allocation section. + /// + /// @param[in] global_variable + /// The variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool MaterializeInternalVariable(llvm::GlobalVariable *global_variable); + + //------------------------------------------------------------------ + /// Handle a single externally-defined variable + /// + /// @param[in] value + /// The variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool MaybeHandleVariable(llvm::Value *value); + + //------------------------------------------------------------------ + /// Handle a single externally-defined symbol + /// + /// @param[in] symbol + /// The symbol. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool HandleSymbol(llvm::Value *symbol); + + //------------------------------------------------------------------ + /// Handle a single externally-defined Objective-C class + /// + /// @param[in] classlist_reference + /// The reference, usually "01L_OBJC_CLASSLIST_REFERENCES_$_n" + /// where n (if present) is an index. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool HandleObjCClass(llvm::Value *classlist_reference); + + //------------------------------------------------------------------ + /// Handle all the arguments to a function call + /// + /// @param[in] C + /// The call instruction. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool MaybeHandleCallArguments(llvm::CallInst *call_inst); + + //------------------------------------------------------------------ + /// Resolve variable references in calls to external functions + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool ResolveCalls(llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// Remove calls to __cxa_atexit, which should never be generated by + /// expressions. + /// + /// @param[in] call_inst + /// The call instruction. + /// + /// @return + /// True if the scan was successful; false if some operation + /// failed + //------------------------------------------------------------------ + bool RemoveCXAAtExit(llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool ResolveExternals(llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A basic block-level pass to excise guard variables from the code. + /// The result for the function is passed through Clang as a static + /// variable. Static variables normally have guard variables to + /// ensure that they are only initialized once. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Rewrite a load to a guard variable to return constant 0. + /// + /// @param[in] guard_load + /// The load instruction to zero out. + //------------------------------------------------------------------ + void TurnGuardLoadIntoZero(llvm::Instruction *guard_load); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool RemoveGuards(llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A function-level pass to make all external variable references + /// point at the correct offsets from the void* passed into the + /// function. ClangExpressionDeclMap::DoStructLayout() must be called + /// beforehand, so that the offsets are valid. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool ReplaceVariables(llvm::Function &llvm_function); + + /// Flags + bool m_resolve_vars; ///< True if external variable references and persistent + ///variable references should be resolved + lldb_private::ConstString + m_func_name; ///< The name of the function to translate + lldb_private::ConstString + m_result_name; ///< The name of the result variable ($0, $1, ...) + lldb_private::TypeFromParser + m_result_type; ///< The type of the result variable. + llvm::Module *m_module; ///< The module being processed, or NULL if that has + ///not been determined yet. + std::unique_ptr<llvm::DataLayout> m_target_data; ///< The target data for the + ///module being processed, or + ///NULL if there is no + ///module. + lldb_private::ClangExpressionDeclMap + *m_decl_map; ///< The DeclMap containing the Decls + llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function + ///CFStringCreateWithBytes, cast to + ///the + /// appropriate function pointer type + llvm::Constant *m_sel_registerName; ///< The address of the function + ///sel_registerName, cast to the + ///appropriate + /// function pointer type + llvm::IntegerType + *m_intptr_ty; ///< The type of an integer large enough to hold a pointer. + lldb_private::Stream + &m_error_stream; ///< The stream on which errors should be printed + lldb_private::IRExecutionUnit & + m_execution_unit; ///< The execution unit containing the IR being created. + + llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that + ///writes to the result variable. If + /// m_has_side_effects is true, this is NULL. + bool m_result_is_pointer; ///< True if the function's result in the AST is a + ///pointer (see comments in + /// ASTResultSynthesizer::SynthesizeBodyResult) + + llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be + ///replaced by a pointer to the + ///final + /// location of the static allocation. + + //------------------------------------------------------------------ + /// UnfoldConstant operates on a constant [Old] which has just been + /// replaced with a value [New]. We assume that new_value has + /// been properly placed early in the function, in front of the + /// first instruction in the entry basic block + /// [FirstEntryInstruction]. + /// + /// UnfoldConstant reads through the uses of Old and replaces Old + /// in those uses with New. Where those uses are constants, the + /// function generates new instructions to compute the result of the + /// new, non-constant expression and places them before + /// FirstEntryInstruction. These instructions replace the constant + /// uses, so UnfoldConstant calls itself recursively for those. + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + + class FunctionValueCache { + public: + typedef std::function<llvm::Value *(llvm::Function *)> Maker; + + FunctionValueCache(Maker const &maker); + ~FunctionValueCache(); + llvm::Value *GetValue(llvm::Function *function); + + private: + Maker const m_maker; + typedef std::map<llvm::Function *, llvm::Value *> FunctionValueMap; + FunctionValueMap m_values; + }; + + FunctionValueCache m_entry_instruction_finder; + + static bool UnfoldConstant(llvm::Constant *old_constant, + llvm::Function *llvm_function, + FunctionValueCache &value_maker, + FunctionValueCache &entry_instruction_finder, + lldb_private::Stream &error_stream); + + //------------------------------------------------------------------ + /// Construct a reference to m_reloc_placeholder with a given type + /// and offset. This typically happens after inserting data into + /// m_data_allocator. + /// + /// @param[in] type + /// The type of the value being loaded. + /// + /// @param[in] offset + /// The offset of the value from the base of m_data_allocator. + /// + /// @return + /// The Constant for the reference, usually a ConstantExpr. + //------------------------------------------------------------------ + llvm::Constant *BuildRelocation(llvm::Type *type, uint64_t offset); + //------------------------------------------------------------------ + /// Commit the allocation in m_data_allocator and use its final + /// location to replace m_reloc_placeholder. + /// + /// @param[in] module + /// The module that m_data_allocator resides in + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool CompleteDataAllocation(); }; #endif // liblldb_IRForTarget_h_ |