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);
                 }
             }
         }