The "desired result type" code in the expression
parser has hitherto been an implementation waiting
for a use.  I have now tied the '-o' option for
the expression command -- which indicates that the
result is an Objective-C object and needs to be
printed -- to the ExpressionParser, which
communicates the desired type to Clang.

Now, if the result of an expression is determined
by an Objective-C method call for which there is
no type information, that result is implicitly
cast to id if and only if the -o option is passed
to the expression command.  (Otherwise if there
is no explicit cast Clang will issue an error.
This behavior is identical to what happened before
r146756.)

Also added a testcase for -o enabled and disabled.


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@147099 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBFrame.cpp b/source/API/SBFrame.cpp
index a541047..3a3c582 100644
--- a/source/API/SBFrame.cpp
+++ b/source/API/SBFrame.cpp
@@ -756,12 +756,14 @@
         Host::SetCrashDescriptionWithFormat ("SBFrame::EvaluateExpression (expr = \"%s\", fetch_dynamic_value = %u) %s",
                                              expr, fetch_dynamic_value, frame_description.GetString().c_str());
 
+        const bool coerce_to_id = false;
         const bool unwind_on_error = true;
         const bool keep_in_memory = false;
 
         exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr, 
                                                                                            m_opaque_sp.get(),
                                                                                            eExecutionPolicyOnlyWhenNeeded,
+                                                                                           coerce_to_id,
                                                                                            unwind_on_error, 
                                                                                            keep_in_memory, 
                                                                                            fetch_dynamic_value, 
diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp
index 654336d..1ed3fea 100644
--- a/source/API/SBValue.cpp
+++ b/source/API/SBValue.cpp
@@ -388,6 +388,7 @@
         m_opaque_sp->GetUpdatePoint().GetTargetSP()->EvaluateExpression (expression,
                                                                          m_opaque_sp->GetExecutionContextScope()->CalculateStackFrame(),
                                                                          eExecutionPolicyOnlyWhenNeeded,
+                                                                         false, // coerce to id
                                                                          true, // unwind on error
                                                                          true, // keep in memory
                                                                          eNoDynamicValues,
diff --git a/source/Breakpoint/BreakpointOptions.cpp b/source/Breakpoint/BreakpointOptions.cpp
index c2277db..79ffa32 100644
--- a/source/Breakpoint/BreakpointOptions.cpp
+++ b/source/Breakpoint/BreakpointOptions.cpp
@@ -60,7 +60,7 @@
     if (rhs.m_thread_spec_ap.get() != NULL)
         m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get()));
     if (rhs.m_condition_ap.get())
-        m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL, lldb::eLanguageTypeUnknown));
+        m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
 }
 
 //----------------------------------------------------------------------
@@ -77,7 +77,7 @@
     if (rhs.m_thread_spec_ap.get() != NULL)
         m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
     if (rhs.m_condition_ap.get())
-        m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL, lldb::eLanguageTypeUnknown));
+        m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
     return *this;
 }
 
@@ -166,7 +166,7 @@
     }
     else
     {
-        m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown));
+        m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
     }
 }
 
@@ -196,13 +196,9 @@
         process->SetDynamicCheckers(dynamic_checkers);
     }
     
-    // Get the boolean type from the process's scratch AST context
-    ClangASTContext *ast_context = exe_ctx.GetTargetRef().GetScratchClangASTContext();
-    TypeFromUser bool_type(ast_context->GetBuiltInType_bool(), ast_context->getASTContext());
-
     const bool keep_in_memory = false;
     
-    if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type, eExecutionPolicyAlways, keep_in_memory))
+    if (!m_condition_ap->Parse (error_stream, exe_ctx, eExecutionPolicyAlways, keep_in_memory))
     {
         // Errors mean we should stop.
         return NULL;
diff --git a/source/Breakpoint/Watchpoint.cpp b/source/Breakpoint/Watchpoint.cpp
index 4645b60..e9b314b 100644
--- a/source/Breakpoint/Watchpoint.cpp
+++ b/source/Breakpoint/Watchpoint.cpp
@@ -212,7 +212,7 @@
     else
     {
         // Pass NULL for expr_prefix (no translation-unit level definitions).
-        m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown));
+        m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
     }
 }
 
diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp
index 5134b28..e2ce4b2 100644
--- a/source/Commands/CommandObjectExpression.cpp
+++ b/source/Commands/CommandObjectExpression.cpp
@@ -312,6 +312,7 @@
         exe_results = target->EvaluateExpression (expr, 
                                                   m_exe_ctx.GetFramePtr(),
                                                   eExecutionPolicyOnlyWhenNeeded,
+                                                  m_command_options.print_object,
                                                   m_command_options.unwind_on_error,
                                                   keep_in_memory, 
                                                   use_dynamic, 
diff --git a/source/Expression/ASTResultSynthesizer.cpp b/source/Expression/ASTResultSynthesizer.cpp
index 0df2a5e..de17ebd 100644
--- a/source/Expression/ASTResultSynthesizer.cpp
+++ b/source/Expression/ASTResultSynthesizer.cpp
@@ -30,14 +30,12 @@
 using namespace lldb_private;
 
 ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
-                                           TypeFromUser desired_type,
                                            Target &target) :
     m_ast_context (NULL),
     m_passthrough (passthrough),
     m_passthrough_sema (NULL),
     m_target (target),
-    m_sema (NULL),
-    m_desired_type (desired_type)
+    m_sema (NULL)
 {
     if (!m_passthrough)
         return;
diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp
index 351c484..9128223 100644
--- a/source/Expression/ClangExpressionParser.cpp
+++ b/source/Expression/ClangExpressionParser.cpp
@@ -245,7 +245,10 @@
     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
+    if (expr.DesiredResultType() == ClangExpression::eResultTypeId)
+        m_compiler->getLangOpts().DebuggerCastResultToId = true;
     
     // Set CodeGen options
     m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp
index 8f011c0..c2164c8 100644
--- a/source/Expression/ClangUserExpression.cpp
+++ b/source/Expression/ClangUserExpression.cpp
@@ -45,13 +45,14 @@
 
 ClangUserExpression::ClangUserExpression (const char *expr,
                                           const char *expr_prefix,
-                                          lldb::LanguageType language) :
+                                          lldb::LanguageType language,
+                                          ResultType desired_type) :
     ClangExpression (),
     m_expr_text (expr),
     m_expr_prefix (expr_prefix ? expr_prefix : ""),
     m_language (language),
     m_transformed_text (),
-    m_desired_type (NULL, NULL),
+    m_desired_type (desired_type),
     m_cplusplus (false),
     m_objectivec (false),
     m_needs_object_ptr (false),
@@ -92,7 +93,6 @@
     
     if (!m_result_synthesizer.get())
         m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough,
-                                                            m_desired_type,
                                                             *m_target));
     
     return m_result_synthesizer.get();
@@ -249,7 +249,6 @@
 bool
 ClangUserExpression::Parse (Stream &error_stream, 
                             ExecutionContext &exe_ctx,
-                            TypeFromUser desired_type,
                             lldb_private::ExecutionPolicy execution_policy,
                             bool keep_result_in_memory)
 {
@@ -308,9 +307,7 @@
     //////////////////////////
     // Parse the expression
     //
-    
-    m_desired_type = desired_type;
-    
+        
     m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
     
     if (!m_expr_decl_map->WillParse(exe_ctx))
@@ -638,19 +635,21 @@
 ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
                                lldb_private::ExecutionPolicy execution_policy,
                                lldb::LanguageType language,
+                               ResultType desired_type,
                                bool discard_on_error,
                                const char *expr_cstr,
                                const char *expr_prefix,
                                lldb::ValueObjectSP &result_valobj_sp)
 {
     Error error;
-    return EvaluateWithError (exe_ctx, execution_policy, language, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error);
+    return EvaluateWithError (exe_ctx, execution_policy, language, desired_type, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error);
 }
 
 ExecutionResults
 ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
                                         lldb_private::ExecutionPolicy execution_policy,
                                         lldb::LanguageType language,
+                                        ResultType desired_type,
                                         bool discard_on_error,
                                         const char *expr_cstr,
                                         const char *expr_prefix,
@@ -679,7 +678,7 @@
     if (process == NULL || !process->CanJIT())
         execution_policy = eExecutionPolicyNever;
     
-    ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix, language));
+    ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix, language, desired_type));
 
     StreamString error_stream;
         
@@ -688,7 +687,7 @@
     
     const bool keep_expression_in_memory = true;
     
-    if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), execution_policy, keep_expression_in_memory))
+    if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory))
     {
         if (error_stream.GetString().empty())
             error.SetErrorString ("expression failed to parse, unknown error");
diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp
index bce32be..77cab23 100644
--- a/source/Interpreter/CommandInterpreter.cpp
+++ b/source/Interpreter/CommandInterpreter.cpp
@@ -1112,13 +1112,16 @@
                     target = Host::GetDummyTarget(GetDebugger()).get();
                 if (target)
                 {
+                    const bool coerce_to_id = false;
                     const bool unwind_on_error = true;
                     const bool keep_in_memory = false;
                     ValueObjectSP expr_result_valobj_sp;
                     ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 
                                                                                m_exe_ctx.GetFramePtr(), 
                                                                                eExecutionPolicyOnlyWhenNeeded,
-                                                                               unwind_on_error, keep_in_memory, 
+                                                                               coerce_to_id,
+                                                                               unwind_on_error, 
+                                                                               keep_in_memory, 
                                                                                eNoDynamicValues, 
                                                                                expr_result_valobj_sp);
                     if (expr_result == eExecutionCompleted)
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index fdd6b17..50bcb7a 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -1328,7 +1328,7 @@
                 expr.Printf("dlopen (\"%s\", 2)", path);
                 const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
                 lldb::ValueObjectSP result_valobj_sp;
-                ClangUserExpression::Evaluate (exe_ctx, eExecutionPolicyAlways, lldb::eLanguageTypeUnknown, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
+                ClangUserExpression::Evaluate (exe_ctx, eExecutionPolicyAlways, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
                 error = result_valobj_sp->GetError();
                 if (error.Success())
                 {
@@ -1392,7 +1392,7 @@
                         expr.Printf("dlclose ((void *)0x%llx)", image_addr);
                         const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
                         lldb::ValueObjectSP result_valobj_sp;
-                        ClangUserExpression::Evaluate (exe_ctx, eExecutionPolicyAlways, lldb::eLanguageTypeUnknown, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
+                        ClangUserExpression::Evaluate (exe_ctx, eExecutionPolicyAlways, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
                         if (result_valobj_sp->GetError().Success())
                         {
                             Scalar scalar;
diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp
index f90968f..00c7680 100644
--- a/source/Target/StopInfo.cpp
+++ b/source/Target/StopInfo.cpp
@@ -225,6 +225,7 @@
                         result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx,
                                                                               eExecutionPolicyAlways,
                                                                               lldb::eLanguageTypeUnknown,
+                                                                              ClangUserExpression::eResultTypeAny,
                                                                               discard_on_error,
                                                                               bp_loc_sp->GetConditionText(),
                                                                               NULL,
@@ -494,6 +495,7 @@
                 result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx,
                                                                       eExecutionPolicyAlways,
                                                                       lldb::eLanguageTypeUnknown,
+                                                                      ClangUserExpression::eResultTypeAny,
                                                                       discard_on_error,
                                                                       wp_sp->GetConditionText(),
                                                                       NULL,
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 902ffc7..c31b0b1 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -1462,6 +1462,7 @@
     const char *expr_cstr,
     StackFrame *frame,
     lldb_private::ExecutionPolicy execution_policy,
+    bool coerce_to_id,
     bool unwind_on_error,
     bool keep_in_memory,
     lldb::DynamicValueType use_dynamic,
@@ -1587,6 +1588,7 @@
             execution_results = ClangUserExpression::Evaluate (exe_ctx, 
                                                                execution_policy,
                                                                lldb::eLanguageTypeUnknown,
+                                                               coerce_to_id ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny,
                                                                unwind_on_error,
                                                                expr_cstr, 
                                                                prefix,