Figure out what the fixed expression is, and print it.  Added another target setting to
quietly apply fixits for those who really trust clang's fixits.

Also, moved the retry into ClangUserExpression::Evaluate, where I can make a whole new ClangUserExpression 
to do the work.  Reusing any of the parts of a UserExpression in situ isn't supported at present.

<rdar://problem/25351938>

llvm-svn: 264793
diff --git a/lldb/source/Expression/ExpressionSourceCode.cpp b/lldb/source/Expression/ExpressionSourceCode.cpp
index 5777e3b..4f5305b 100644
--- a/lldb/source/Expression/ExpressionSourceCode.cpp
+++ b/lldb/source/Expression/ExpressionSourceCode.cpp
@@ -61,6 +61,9 @@
 }
 )";
 
+static const char *c_start_marker = "    /*LLDB_BODY_START*/\n    ";
+static const char *c_end_marker   = ";\n    /*LLDB_BODY_END*/\n";
+
 namespace {
 
 class AddMacroState
@@ -301,6 +304,22 @@
                            target_specific_defines,
                            m_prefix.c_str());
         
+        // First construct a tagged form of the user expression so we can find it later:
+        std::string tagged_body;
+        switch (wrapping_language)
+        {
+            default:
+                tagged_body = m_body;
+                break;
+            case lldb::eLanguageTypeC:
+            case lldb::eLanguageTypeC_plus_plus:
+            case lldb::eLanguageTypeObjC:
+                tagged_body.append(c_start_marker);
+                tagged_body.append(m_body);
+                tagged_body.append(c_end_marker);
+                break;
+            
+        }
         switch (wrapping_language) 
         {
         default:
@@ -310,23 +329,23 @@
                                "%s(void *$__lldb_arg)          \n"
                                "{                              \n"
                                "    %s;                        \n"
-                               "    %s;                        \n" 
+                               "%s"
                                "}                              \n",
                                m_name.c_str(),
                                lldb_local_var_decls.GetData(),
-                               m_body.c_str());
+                               tagged_body.c_str());
             break;
         case lldb::eLanguageTypeC_plus_plus:
             wrap_stream.Printf("void                                   \n"
                                "$__lldb_class::%s(void *$__lldb_arg) %s\n"
                                "{                                      \n"
                                "    %s;                                \n"
-                               "    %s;                                \n" 
+                               "%s"
                                "}                                      \n",
                                m_name.c_str(),
                                (const_object ? "const" : ""),
                                lldb_local_var_decls.GetData(),
-                               m_body.c_str());
+                               tagged_body.c_str());
             break;
         case lldb::eLanguageTypeObjC:
             if (static_method)
@@ -337,12 +356,12 @@
                                    "@implementation $__lldb_objc_class ($__lldb_category)   \n"
                                    "+(void)%s:(void *)$__lldb_arg                           \n"
                                    "{                                                       \n"
-                                   "    %s;                                                 \n"
+                                   "%s"
                                    "}                                                       \n"
                                    "@end                                                    \n",
                                    m_name.c_str(),
                                    m_name.c_str(),
-                                   m_body.c_str());
+                                   tagged_body.c_str());
             }
             else
             {
@@ -352,12 +371,12 @@
                                    "@implementation $__lldb_objc_class ($__lldb_category)  \n"
                                    "-(void)%s:(void *)$__lldb_arg                          \n"
                                    "{                                                      \n"
-                                   "    %s;                                                \n"
+                                   "%s"
                                    "}                                                      \n"
                                    "@end                                                   \n",
                                    m_name.c_str(),
                                    m_name.c_str(),
-                                   m_body.c_str());
+                                   tagged_body.c_str());
             }
             break;
         }
@@ -371,3 +390,35 @@
 
     return true;
 }
+
+bool
+ExpressionSourceCode::GetOriginalBodyBounds(std::string transformed_text,
+                                            lldb::LanguageType wrapping_language,
+                                            size_t &start_loc,
+                                            size_t &end_loc)
+{
+    const char *start_marker;
+    const char *end_marker;
+    
+    switch (wrapping_language)
+    {
+    default:
+        return false;
+    case lldb::eLanguageTypeC:
+    case lldb::eLanguageTypeC_plus_plus:
+    case lldb::eLanguageTypeObjC:
+        start_marker = c_start_marker;
+        end_marker = c_end_marker;
+        break;
+    }
+    
+    start_loc = transformed_text.find(start_marker);
+    if (start_loc == std::string::npos)
+        return false;
+    start_loc += strlen(start_marker);
+    end_loc  = transformed_text.find(end_marker);
+    if (end_loc == std::string::npos)
+        return false;
+    return true;
+}
+
diff --git a/lldb/source/Expression/REPL.cpp b/lldb/source/Expression/REPL.cpp
index 850099c..30f2560 100644
--- a/lldb/source/Expression/REPL.cpp
+++ b/lldb/source/Expression/REPL.cpp
@@ -363,6 +363,7 @@
                                                                                   result_valobj_sp,
                                                                                   error,
                                                                                   0, // Line offset
+                                                                                  nullptr, // Fixed Expression
                                                                                   &jit_module_sp);
             
             //CommandInterpreter &ci = debugger.GetCommandInterpreter();
diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp
index 1982993..b58bf1f 100644
--- a/lldb/source/Expression/UserExpression.cpp
+++ b/lldb/source/Expression/UserExpression.cpp
@@ -160,6 +160,7 @@
                                lldb::ValueObjectSP &result_valobj_sp,
                                Error &error,
                                uint32_t line_offset,
+                               std::string *fixed_expression,
                                lldb::ModuleSP *jit_module_sp_ptr)
 {
     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
@@ -253,18 +254,65 @@
     }
 
     DiagnosticManager diagnostic_manager;
-    diagnostic_manager.SetAutoApplyFixIts(options.GetAutoApplyFixIts());
 
-    if (!user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy, keep_expression_in_memory,
-                                   generate_debug_info))
+    bool parse_success = user_expression_sp->Parse(diagnostic_manager,
+                                                   exe_ctx,
+                                                   execution_policy,
+                                                   keep_expression_in_memory,
+                                                   generate_debug_info);
+    
+    // Calculate the fixed expression always, since we need it for errors.
+    std::string tmp_fixed_expression;
+    if (fixed_expression == nullptr)
+        fixed_expression = &tmp_fixed_expression;
+
+    const char *fixed_text = user_expression_sp->GetFixedText();
+    if (fixed_text != nullptr)
+            fixed_expression->append(fixed_text);
+    
+    // If there is a fixed expression, try to parse it:
+    if (!parse_success)
     {
         execution_results = lldb::eExpressionParseError;
-        if (!diagnostic_manager.Diagnostics().size())
-            error.SetExpressionError(execution_results, "expression failed to parse, unknown error");
-        else
-            error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str());
+        if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts())
+        {
+            lldb::UserExpressionSP fixed_expression_sp(target->GetUserExpressionForLanguage (fixed_expression->c_str(),
+                                                                                             full_prefix,
+                                                                                             language,
+                                                                                             desired_type,
+                                                                                             options,
+                                                                                             error));
+            DiagnosticManager fixed_diagnostic_manager;
+            parse_success = fixed_expression_sp->Parse(fixed_diagnostic_manager,
+                                                       exe_ctx,
+                                                       execution_policy,
+                                                       keep_expression_in_memory,
+                                                       generate_debug_info);
+            if (parse_success)
+            {
+                diagnostic_manager.Clear();
+                user_expression_sp = fixed_expression_sp;
+            }
+        }
+        
+        if (!parse_success)
+        {
+            if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts())
+            {
+                error.SetExpressionErrorWithFormat(execution_results, "expression failed to parse, fixed expression suggested:\n  %s",
+                                                   fixed_expression->c_str());
+            }
+            else
+            {
+                if (!diagnostic_manager.Diagnostics().size())
+                    error.SetExpressionError(execution_results, "expression failed to parse, unknown error");
+                else
+                    error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str());
+            }
+        }
     }
-    else
+    
+    if (parse_success)
     {
         // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
         if (jit_module_sp_ptr)