[Lldb-commits] [lldb] r138383 - in /lldb/trunk: include/lldb/Core/ include/lldb/Expression/ source/Commands/ source/Expression/ test/expression_command/persistent_types/
Sean Callanan
scallanan at apple.com
Tue Aug 23 14:20:51 PDT 2011
Author: spyffe
Date: Tue Aug 23 16:20:51 2011
New Revision: 138383
URL: http://llvm.org/viewvc/llvm-project?rev=138383&view=rev
Log:
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.
Added:
lldb/trunk/test/expression_command/persistent_types/
lldb/trunk/test/expression_command/persistent_types/Makefile
lldb/trunk/test/expression_command/persistent_types/TestPersistentTypes.py
lldb/trunk/test/expression_command/persistent_types/main.c
Modified:
lldb/trunk/include/lldb/Core/ClangForward.h
lldb/trunk/include/lldb/Expression/ASTResultSynthesizer.h
lldb/trunk/include/lldb/Expression/ClangPersistentVariables.h
lldb/trunk/include/lldb/Expression/ClangUserExpression.h
lldb/trunk/source/Commands/CommandObjectExpression.cpp
lldb/trunk/source/Expression/ASTResultSynthesizer.cpp
lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
lldb/trunk/source/Expression/ClangExpressionParser.cpp
lldb/trunk/source/Expression/ClangPersistentVariables.cpp
lldb/trunk/source/Expression/ClangUserExpression.cpp
Modified: lldb/trunk/include/lldb/Core/ClangForward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ClangForward.h?rev=138383&r1=138382&r2=138383&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ClangForward.h (original)
+++ lldb/trunk/include/lldb/Core/ClangForward.h Tue Aug 23 16:20:51 2011
@@ -110,6 +110,7 @@
class TextDiagnosticBuffer;
class TranslationUnitDecl;
class Type;
+ class TypeDecl;
class TypedefDecl;
class TypesCompatibleExpr;
class UnaryOperator;
Modified: lldb/trunk/include/lldb/Expression/ASTResultSynthesizer.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ASTResultSynthesizer.h?rev=138383&r1=138382&r2=138383&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ASTResultSynthesizer.h (original)
+++ lldb/trunk/include/lldb/Expression/ASTResultSynthesizer.h Tue Aug 23 16:20:51 2011
@@ -44,9 +44,15 @@
/// @param[in] desired_type
/// The type that the result should have. May be initialized with a
/// NULL type, in which case the type is inferred.
+ ///
+ /// @param[in] scratch_ast_context
+ /// If non-NULL, an AST context to populate with the persistent types
+ /// found in the expression.
//----------------------------------------------------------------------
ASTResultSynthesizer(clang::ASTConsumer *passthrough,
- TypeFromUser desired_type);
+ TypeFromUser desired_type,
+ clang::ASTContext &scratch_ast_context,
+ ClangPersistentVariables &persistent_vars);
//----------------------------------------------------------------------
/// Destructor
@@ -140,18 +146,43 @@
bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl);
//----------------------------------------------------------------------
- /// Process a functionbody and produce the result variable and
+ /// 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);
+
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::ASTContext &m_scratch_ast_context; ///< The AST context to install persistent types into.
+ ClangPersistentVariables &m_persistent_vars;///< The persistent variable manager to register persistent types with.
clang::Sema *m_sema; ///< The Sema to use.
TypeFromUser m_desired_type; ///< If non-NULL, the type to coerce the result to.
};
Modified: lldb/trunk/include/lldb/Expression/ClangPersistentVariables.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangPersistentVariables.h?rev=138383&r1=138382&r2=138383&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangPersistentVariables.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangPersistentVariables.h Tue Aug 23 16:20:51 2011
@@ -11,10 +11,11 @@
#define liblldb_ClangPersistentVariables_h_
#include "lldb/Expression/ClangExpressionVariable.h"
+#include "llvm/ADT/DenseMap.h"
namespace lldb_private
{
-
+
//----------------------------------------------------------------------
/// @class ClangPersistentVariables ClangPersistentVariables.h "lldb/Expression/ClangPersistentVariables.h"
/// @brief Manages persistent values that need to be preserved between expression invocations.
@@ -52,8 +53,18 @@
ConstString
GetNextPersistentVariableName ();
+ void
+ RegisterPersistentType (const ConstString &name,
+ clang::TypeDecl *tag_decl);
+
+ clang::TypeDecl *
+ GetPersistentType (const ConstString &name);
+
private:
- uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName().
+ uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName().
+
+ typedef llvm::DenseMap<const char *, clang::TypeDecl *> PersistentTypeMap;
+ PersistentTypeMap m_persistent_types; ///< The persistent types declared by the user.
};
}
Modified: lldb/trunk/include/lldb/Expression/ClangUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangUserExpression.h?rev=138383&r1=138382&r2=138383&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangUserExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangUserExpression.h Tue Aug 23 16:20:51 2011
@@ -290,7 +290,8 @@
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp,
Error &error);
-
+
+ static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression.
private:
//------------------------------------------------------------------
/// Populate m_cplusplus and m_objetivec based on the environment.
@@ -320,6 +321,7 @@
bool m_objectivec; ///< True if the expression is compiled as an Objective-C method (true if it was parsed when exe_ctx was in an Objective-C method).
bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and passed in. False if the expression doesn't really use them and they can be NULL.
bool m_const_object; ///< True if "this" is const.
+ Target *m_target; ///< The target for storing persistent data like types and variables.
lldb::ClangExpressionVariableSP m_const_result; ///< The statically-computed result of the expression. NULL if it could not be computed statically or the expression has side effects.
};
Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=138383&r1=138382&r2=138383&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Tue Aug 23 16:20:51 2011
@@ -347,24 +347,34 @@
}
else
{
- const char *error_cstr = result_valobj_sp->GetError().AsCString();
- if (error_cstr && error_cstr[0])
+ if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult)
{
- int error_cstr_len = strlen (error_cstr);
- const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';
- if (strstr(error_cstr, "error:") != error_cstr)
- error_stream->PutCString ("error: ");
- error_stream->Write(error_cstr, error_cstr_len);
- if (!ends_with_newline)
- error_stream->EOL();
+ error_stream->PutCString("<no result>\n");
+
+ if (result)
+ result->SetStatus (eReturnStatusSuccessFinishResult);
}
else
{
- error_stream->PutCString ("error: unknown error\n");
+ const char *error_cstr = result_valobj_sp->GetError().AsCString();
+ if (error_cstr && error_cstr[0])
+ {
+ int error_cstr_len = strlen (error_cstr);
+ const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';
+ if (strstr(error_cstr, "error:") != error_cstr)
+ error_stream->PutCString ("error: ");
+ error_stream->Write(error_cstr, error_cstr_len);
+ if (!ends_with_newline)
+ error_stream->EOL();
+ }
+ else
+ {
+ error_stream->PutCString ("error: unknown error\n");
+ }
+
+ if (result)
+ result->SetStatus (eReturnStatusFailed);
}
-
- if (result)
- result->SetStatus (eReturnStatusFailed);
}
}
}
Modified: lldb/trunk/source/Expression/ASTResultSynthesizer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ASTResultSynthesizer.cpp?rev=138383&r1=138382&r2=138383&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ASTResultSynthesizer.cpp (original)
+++ lldb/trunk/source/Expression/ASTResultSynthesizer.cpp Tue Aug 23 16:20:51 2011
@@ -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::HandleTagDeclDefinition(TagDecl *D)
+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);
}
Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=138383&r1=138382&r2=138383&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Tue Aug 23 16:20:51 2011
@@ -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)
Modified: lldb/trunk/source/Expression/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionParser.cpp?rev=138383&r1=138382&r2=138383&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionParser.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionParser.cpp Tue Aug 23 16:20:51 2011
@@ -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;
Modified: lldb/trunk/source/Expression/ClangPersistentVariables.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangPersistentVariables.cpp?rev=138383&r1=138382&r2=138383&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangPersistentVariables.cpp (original)
+++ lldb/trunk/source/Expression/ClangPersistentVariables.cpp Tue Aug 23 16:20:51 2011
@@ -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;
+}
Modified: lldb/trunk/source/Expression/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?rev=138383&r1=138382&r2=138383&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangUserExpression.cpp Tue Aug 23 16:20:51 2011
@@ -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);
}
}
}
Added: lldb/trunk/test/expression_command/persistent_types/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/expression_command/persistent_types/Makefile?rev=138383&view=auto
==============================================================================
--- lldb/trunk/test/expression_command/persistent_types/Makefile (added)
+++ lldb/trunk/test/expression_command/persistent_types/Makefile Tue Aug 23 16:20:51 2011
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules
Added: lldb/trunk/test/expression_command/persistent_types/TestPersistentTypes.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/expression_command/persistent_types/TestPersistentTypes.py?rev=138383&view=auto
==============================================================================
--- lldb/trunk/test/expression_command/persistent_types/TestPersistentTypes.py (added)
+++ lldb/trunk/test/expression_command/persistent_types/TestPersistentTypes.py Tue Aug 23 16:20:51 2011
@@ -0,0 +1,41 @@
+"""
+Test that lldb persistent types works correctly.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class PersistenttypesTestCase(TestBase):
+
+ mydir = os.path.join("expression_command", "persistent_types")
+
+ def test_persistent_types(self):
+ """Test that lldb persistent types works correctly."""
+ self.buildDefault()
+
+ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+ self.runCmd("breakpoint set --name main")
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ self.runCmd("expression struct $foo { int a; int b; };")
+
+ self.expect("expression struct $foo $my_foo; $my_foo.a = 2; $my_foo.b = 3;",
+ startstr = "(int) $0 = 3")
+
+ self.expect("expression $my_foo",
+ substrs = ['a = 2', 'b = 3'])
+
+ self.runCmd("expression typedef int $bar")
+
+ self.expect("expression $bar i = 5; i",
+ startstr = "($bar) $1 = 5")
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
Added: lldb/trunk/test/expression_command/persistent_types/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/expression_command/persistent_types/main.c?rev=138383&view=auto
==============================================================================
--- lldb/trunk/test/expression_command/persistent_types/main.c (added)
+++ lldb/trunk/test/expression_command/persistent_types/main.c Tue Aug 23 16:20:51 2011
@@ -0,0 +1,13 @@
+//===-- main.c --------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+int main (int argc, char const *argv[])
+{
+ return 0;
+}
More information about the lldb-commits
mailing list