Added support for persistent types to the
expression parser. You can use a persistent
type like this:
(lldb) expr struct $foo { int a; int b; };
(lldb) struct $foo i; i.a = 2; i.b = 3; i
($foo) $0 = {
(int) a = 2
(int) b = 3
}
typedefs work similarly.
This patch affects the following files:
test/expression_command/persistent_types/*
A test case for persistent types,
in particular structs and typedefs.
ClangForward.h
Added TypeDecl, needed to declare some
functions in ASTResultSynthesizer.h
ClangPersistentVariables.[h,cpp]
Added a list of persistent types to the
persistent variable store.
ASTResultSynthesizer.[h,cpp]
Made the AST result synthesizer iterate
across TypeDecls in the expression, and
record any persistent types found. Also
made a minor documentation fix.
ClangUserExpression.[h,cpp]
Extended the user expression class to
keep the state needed to report the
persistent variable store for the target
to the AST result synthesizers.
Also introduced a new error code for
expressions that executed normally but
did not return a result.
CommandObjectExpression.cpp
Improved output for expressions (like
declarations of new persistent types) that
don't return a result. This is no longer
treated as an error.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@138383 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/ASTResultSynthesizer.cpp b/source/Expression/ASTResultSynthesizer.cpp
index 1125d62..b2b593b 100644
--- a/source/Expression/ASTResultSynthesizer.cpp
+++ b/source/Expression/ASTResultSynthesizer.cpp
@@ -19,19 +19,25 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "lldb/Core/Log.h"
+#include "lldb/Expression/ClangPersistentVariables.h"
#include "lldb/Expression/ASTResultSynthesizer.h"
+#include "lldb/Symbol/ClangASTContext.h"
using namespace llvm;
using namespace clang;
using namespace lldb_private;
ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
- TypeFromUser desired_type) :
+ TypeFromUser desired_type,
+ ASTContext &scratch_ast_context,
+ ClangPersistentVariables &persistent_vars) :
m_ast_context (NULL),
m_passthrough (passthrough),
m_passthrough_sema (NULL),
m_sema (NULL),
- m_desired_type (desired_type)
+ m_desired_type (desired_type),
+ m_scratch_ast_context (scratch_ast_context),
+ m_persistent_vars (persistent_vars)
{
if (!m_passthrough)
return;
@@ -87,6 +93,7 @@
if (m_ast_context &&
!method_decl->getSelector().getAsString().compare("$__lldb_expr:"))
{
+ RecordPersistentTypes(method_decl);
SynthesizeObjCMethodResult(method_decl);
}
}
@@ -95,6 +102,7 @@
if (m_ast_context &&
!function_decl->getNameInfo().getAsString().compare("$__lldb_expr"))
{
+ RecordPersistentTypes(function_decl);
SynthesizeFunctionResult(function_decl);
}
}
@@ -397,9 +405,51 @@
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::MaybeRecordPersistentType(TypeDecl *D)
+{
+ if (!D->getIdentifier())
+ return;
+
+ StringRef name = D->getName();
+
+ if (name.size() == 0 || name[0] != '$')
+ return;
+
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ ConstString name_cs(name.str().c_str());
+
+ if (log)
+ log->Printf ("Recording persistent type %s\n", name_cs.GetCString());
+
+ Decl *D_scratch = ClangASTContext::CopyDecl(&m_scratch_ast_context,
+ m_ast_context,
+ D);
+
+ TypeDecl *TD_scratch = dyn_cast<TypeDecl>(D_scratch);
+
+ if (TD_scratch)
+ m_persistent_vars.RegisterPersistentType(name_cs, TD_scratch);
+}
+
void
ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
-{
+{
if (m_passthrough)
m_passthrough->HandleTagDeclDefinition(D);
}
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
index 08e7724..75387a9 100644
--- a/source/Expression/ClangExpressionDeclMap.cpp
+++ b/source/Expression/ClangExpressionDeclMap.cpp
@@ -1945,6 +1945,42 @@
return;
}
+ do
+ {
+ if (!m_parser_vars->m_exe_ctx->target)
+ break;
+
+ ClangASTContext *scratch_clang_ast_context = m_parser_vars->m_exe_ctx->target->GetScratchClangASTContext();
+
+ if (!scratch_clang_ast_context)
+ break;
+
+ ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext();
+
+ if (!scratch_ast_context)
+ break;
+
+ TypeDecl *ptype_type_decl = m_parser_vars->m_persistent_vars->GetPersistentType(name);
+
+ if (!ptype_type_decl)
+ break;
+
+ Decl *parser_ptype_decl = ClangASTContext::CopyDecl(context.GetASTContext(), scratch_ast_context, ptype_type_decl);
+
+ if (!parser_ptype_decl)
+ break;
+
+ TypeDecl *parser_ptype_type_decl = dyn_cast<TypeDecl>(parser_ptype_decl);
+
+ if (!parser_ptype_type_decl)
+ break;
+
+ if (log)
+ log->Printf("Found persistent type %s", name.GetCString());
+
+ context.AddNamedDecl(parser_ptype_type_decl);
+ } while (0);
+
ClangExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name));
if (pvar_sp)
diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp
index 14d8a70..81c03f3 100644
--- a/source/Expression/ClangExpressionParser.cpp
+++ b/source/Expression/ClangExpressionParser.cpp
@@ -234,6 +234,7 @@
m_compiler->getLangOpts().ThreadsafeStatics = false;
m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access
m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
+ //m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients
// Set CodeGen options
m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
diff --git a/source/Expression/ClangPersistentVariables.cpp b/source/Expression/ClangPersistentVariables.cpp
index c4bf885..3da9dc8 100644
--- a/source/Expression/ClangPersistentVariables.cpp
+++ b/source/Expression/ClangPersistentVariables.cpp
@@ -13,6 +13,8 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Value.h"
+#include "llvm/ADT/StringMap.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -53,3 +55,21 @@
ConstString name(name_cstr);
return name;
}
+
+void
+ClangPersistentVariables::RegisterPersistentType (const ConstString &name,
+ clang::TypeDecl *type_decl)
+{
+ m_persistent_types.insert(std::pair<const char*, clang::TypeDecl*>(name.GetCString(), type_decl));
+}
+
+clang::TypeDecl *
+ClangPersistentVariables::GetPersistentType (const ConstString &name)
+{
+ PersistentTypeMap::const_iterator i = m_persistent_types.find(name.GetCString());
+
+ if (i == m_persistent_types.end())
+ return NULL;
+ else
+ return i->second;
+}
diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp
index 9cd8489..f0a6359 100644
--- a/source/Expression/ClangUserExpression.cpp
+++ b/source/Expression/ClangUserExpression.cpp
@@ -53,7 +53,8 @@
m_objectivec (false),
m_needs_object_ptr (false),
m_const_object (false),
- m_const_result ()
+ m_const_result (),
+ m_target (NULL)
{
}
@@ -64,8 +65,15 @@
clang::ASTConsumer *
ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
{
+ ClangASTContext *clang_ast_context = m_target->GetScratchClangASTContext();
+
+ if (!clang_ast_context)
+ return NULL;
+
return new ASTResultSynthesizer(passthrough,
- m_desired_type);
+ m_desired_type,
+ *m_target->GetScratchClangASTContext()->getASTContext(),
+ m_target->GetPersistentVariables());
}
void
@@ -88,6 +96,8 @@
if (!decl_context)
return;
+
+ m_target = exe_ctx.target;
if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context))
{
@@ -718,7 +728,7 @@
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
- error.SetErrorString ("Expression did not return a result");
+ error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
}
}
}