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.
llvm-svn: 138383
diff --git a/lldb/source/Expression/ASTResultSynthesizer.cpp b/lldb/source/Expression/ASTResultSynthesizer.cpp
index 1125d62..b2b593b 100644
--- a/lldb/source/Expression/ASTResultSynthesizer.cpp
+++ b/lldb/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);
}