summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/ExpressionParser/Clang
diff options
context:
space:
mode:
authorKate Stone <katherine.stone@apple.com>2016-09-06 20:57:50 +0000
committerKate Stone <katherine.stone@apple.com>2016-09-06 20:57:50 +0000
commitb9c1b51e45b845debb76d8658edabca70ca56079 (patch)
treedfcb5a13ef2b014202340f47036da383eaee74aa /lldb/source/Plugins/ExpressionParser/Clang
parentd5aa73376966339caad04013510626ec2e42c760 (diff)
downloadbcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.tar.gz
bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.zip
*** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style. This kind of mass change has *** two obvious implications: Firstly, merging this particular commit into a downstream fork may be a huge effort. Alternatively, it may be worth merging all changes up to this commit, performing the same reformatting operation locally, and then discarding the merge for this particular commit. The commands used to accomplish this reformatting were as follows (with current working directory as the root of the repository): find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} + find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ; The version of clang-format used was 3.9.0, and autopep8 was 1.2.4. Secondly, “blame” style tools will generally point to this commit instead of a meaningful prior commit. There are alternatives available that will attempt to look through this change and find the appropriate prior commit. YMMV. llvm-svn: 280751
Diffstat (limited to 'lldb/source/Plugins/ExpressionParser/Clang')
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp162
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h33
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp795
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h357
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp277
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h246
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp3146
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h937
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h58
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp3645
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h1226
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h75
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp1639
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h254
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp79
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h359
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp317
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h195
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp1215
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h197
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp106
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h127
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp1093
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h302
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp210
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h152
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp3143
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h1191
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_
OpenPOWER on IntegriCloud