I can see how it would be useful, but i do think it should be possible to disable and/or warn about On Thu, Mar 24, 2016 at 7:40 PM Jason Molenda <jmole...@apple.com> wrote:
> The specific example Jim gave (./->) is a very common complaint of people > coming from gdb. > > gdb's hand-rolled parser would realize that when you -> on an object, that > doesn't make sense and silently correct it to . for you. In practice, when > you're examining local variables, you often don't remember whether > something is an object or a pointer to an object - especially when you are > dereferencing down a few levels (e.g. "p > myvar->subelem.valcontainer->value"). > > Because lldb uses clang, we have to follow the rules of the language (for > the most part) - this is likely the only way we could accomplish something > similar in lldb. > > > > On Mar 24, 2016, at 7:23 PM, Zachary Turner via lldb-commits < > lldb-commits@lists.llvm.org> wrote: > > > > This seems like an odd thing to do by default. Is there going to be a > setting to turn this off? Seems to me like off should be default > > > > An enumerated setting would be even nicer, where one option is "report" > that just doesn't apply any FixIts, but prints a message saying "did you > mean Foo->bar()?" > > On Thu, Mar 24, 2016 at 7:02 PM Jim Ingham via lldb-commits < > lldb-commits@lists.llvm.org> wrote: > > Author: jingham > > Date: Thu Mar 24 20:57:14 2016 > > New Revision: 264379 > > > > URL: http://llvm.org/viewvc/llvm-project?rev=264379&view=rev > > Log: > > Use Clang's FixItHints to correct expressions with "trivial" mistakes > (e.g. "." for "->".) > > This feature is controlled by an expression command option, a target > property and the > > SBExpressionOptions setting. FixIt's are only applied to > UserExpressions, not UtilityFunctions, > > those you have to get right when you make them. > > > > This is just a first stage. At present the fixits are applied > silently. The next step > > is to tell the user about the applied fixit. > > > > <rdar://problem/25351938> > > > > Added: > > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/ > > > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/Makefile > > > > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py > > > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/main.cpp > > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h > > Modified: > > lldb/trunk/include/lldb/API/SBExpressionOptions.h > > lldb/trunk/include/lldb/Expression/DiagnosticManager.h > > lldb/trunk/include/lldb/Expression/ExpressionParser.h > > lldb/trunk/include/lldb/Target/Target.h > > lldb/trunk/lldb.xcodeproj/project.pbxproj > > lldb/trunk/scripts/interface/SBExpressionOptions.i > > lldb/trunk/source/API/SBExpressionOptions.cpp > > lldb/trunk/source/Commands/CommandObjectExpression.cpp > > lldb/trunk/source/Commands/CommandObjectExpression.h > > lldb/trunk/source/Expression/DiagnosticManager.cpp > > lldb/trunk/source/Expression/UserExpression.cpp > > > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp > > > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h > > > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp > > lldb/trunk/source/Target/Target.cpp > > > > Modified: lldb/trunk/include/lldb/API/SBExpressionOptions.h > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBExpressionOptions.h?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/include/lldb/API/SBExpressionOptions.h (original) > > +++ lldb/trunk/include/lldb/API/SBExpressionOptions.h Thu Mar 24 > 20:57:14 2016 > > @@ -110,6 +110,12 @@ public: > > > > void > > SetPrefix (const char *prefix); > > + > > + void > > + SetAutoApplyFixIts(bool b = true); > > + > > + bool > > + GetAutoApplyFixIts(); > > > > protected: > > > > > > Modified: lldb/trunk/include/lldb/Expression/DiagnosticManager.h > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/DiagnosticManager.h?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/include/lldb/Expression/DiagnosticManager.h (original) > > +++ lldb/trunk/include/lldb/Expression/DiagnosticManager.h Thu Mar 24 > 20:57:14 2016 > > @@ -38,15 +38,82 @@ enum DiagnosticSeverity > > > > const uint32_t LLDB_INVALID_COMPILER_ID = UINT32_MAX; > > > > -struct Diagnostic > > +class Diagnostic > > { > > - std::string message; > > - uint32_t compiler_id; // Compiler-specific diagnostic ID > > - DiagnosticSeverity severity; > > - DiagnosticOrigin origin; > > +friend class DiagnosticManager; > > + > > +public: > > + DiagnosticOrigin getKind() const { return m_origin; } > > + > > + static bool classof(const Diagnostic *diag) > > + { > > + DiagnosticOrigin kind = diag->getKind(); > > + switch (kind) > > + { > > + case eDiagnosticOriginUnknown: > > + case eDiagnosticOriginLLDB: > > + case eDiagnosticOriginGo: > > + case eDiagnosticOriginLLVM: > > + return true; > > + case eDiagnosticOriginClang: > > + case eDiagnosticOriginSwift: > > + return false; > > + } > > + } > > + > > + Diagnostic(const char *message, DiagnosticSeverity severity, > DiagnosticOrigin origin, uint32_t compiler_id) : > > + m_message(message), > > + m_severity(severity), > > + m_origin(origin), > > + m_compiler_id(compiler_id) > > + { > > + } > > + > > + Diagnostic(const Diagnostic &rhs) : > > + m_message(rhs.m_message), > > + m_severity(rhs.m_severity), > > + m_origin(rhs.m_origin), > > + m_compiler_id(rhs.m_compiler_id) > > + { > > + } > > + > > + virtual ~Diagnostic() = default; > > + > > + virtual bool HasFixIts () const { return false; } > > + > > + DiagnosticSeverity > > + GetSeverity() const > > + { > > + return m_severity; > > + } > > + > > + uint32_t > > + GetCompilerID() const > > + { > > + return m_compiler_id; > > + } > > + > > + const char * > > + GetMessage() const > > + { > > + return m_message.c_str(); > > + } > > + > > + void AppendMessage(const char *message, bool precede_with_newline = > true) > > + { > > + if (precede_with_newline) > > + m_message.push_back('\n'); > > + m_message.append(message); > > + } > > + > > +protected: > > + std::string m_message; > > + DiagnosticSeverity m_severity; > > + DiagnosticOrigin m_origin; > > + uint32_t m_compiler_id; // Compiler-specific diagnostic ID > > }; > > > > -typedef std::vector<Diagnostic> DiagnosticList; > > +typedef std::vector<Diagnostic *> DiagnosticList; > > > > class DiagnosticManager > > { > > @@ -55,19 +122,47 @@ public: > > Clear() > > { > > m_diagnostics.clear(); > > + m_auto_apply_fixits = true; > > + m_fixed_expression.clear(); > > } > > > > + // The diagnostic manager holds a list of diagnostics, which are > owned by the manager. > > const DiagnosticList & > > Diagnostics() > > { > > return m_diagnostics; > > } > > - > > + > > + ~DiagnosticManager() > > + { > > + for (Diagnostic *diag : m_diagnostics) > > + { > > + delete diag; > > + } > > + } > > + > > + bool > > + HasFixIts() > > + { > > + for (Diagnostic *diag : m_diagnostics) > > + { > > + if (diag->HasFixIts()) > > + return true; > > + } > > + return false; > > + } > > + > > void > > AddDiagnostic(const char *message, DiagnosticSeverity severity, > DiagnosticOrigin origin, > > uint32_t compiler_id = LLDB_INVALID_COMPILER_ID) > > { > > - m_diagnostics.push_back({std::string(message), compiler_id, > severity, origin}); > > + m_diagnostics.push_back(new Diagnostic(message, severity, > origin, compiler_id)); > > + } > > + > > + void > > + AddDiagnostic(Diagnostic *diagnostic) > > + { > > + m_diagnostics.push_back(diagnostic); > > } > > > > size_t > > @@ -80,11 +175,10 @@ public: > > { > > if (m_diagnostics.size()) > > { > > - m_diagnostics.back().message.push_back('\n'); > > - m_diagnostics.back().message.append(cstr); > > + m_diagnostics.back()->AppendMessage(cstr); > > } > > } > > - > > + > > // Returns a string containing errors in this format: > > // > > // "error: error text\n > > @@ -95,9 +189,36 @@ public: > > > > void > > Dump(Log *log); > > + > > + const std::string & > > + GetFixedExpression() > > + { > > + return m_fixed_expression; > > + } > > + > > + // Moves fixed_expression to the internal storage. > > + void > > + SetFixedExpression(std::string fixed_expression) > > + { > > + m_fixed_expression = std::move(fixed_expression); > > + fixed_expression.clear(); > > + } > > + > > + void > > + SetAutoApplyFixIts(bool auto_apply) > > + { > > + m_auto_apply_fixits = auto_apply; > > + } > > + > > + bool ShouldAutoApplyFixIts() > > + { > > + return m_auto_apply_fixits; > > + } > > > > -private: > > +protected: > > DiagnosticList m_diagnostics; > > + std::string m_fixed_expression; > > + bool m_auto_apply_fixits = true; > > }; > > } > > > > > > Modified: lldb/trunk/include/lldb/Expression/ExpressionParser.h > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ExpressionParser.h?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/include/lldb/Expression/ExpressionParser.h (original) > > +++ lldb/trunk/include/lldb/Expression/ExpressionParser.h Thu Mar 24 > 20:57:14 2016 > > @@ -58,7 +58,7 @@ public: > > /// wrap the expression in anything at all. > > /// > > /// @param[in] diagnostic_manager > > - /// The stream to print errors to. > > + /// The diagnostic manager in which to store the errors and > warnings. > > /// > > /// @return > > /// The number of errors encountered during parsing. 0 means > > @@ -66,6 +66,23 @@ public: > > //------------------------------------------------------------------ > > virtual unsigned > > Parse(DiagnosticManager &diagnostic_manager) = 0; > > + > > + //------------------------------------------------------------------ > > + /// Try to use the FixIts in the diagnostic_manager to rewrite the > > + /// expression. If successful, the rewritten expression is stored > > + /// in the diagnostic_manager, get it out with GetFixedExpression. > > + /// > > + /// @param[in] diagnostic_manager > > + /// The diagnostic manager containing fixit's to apply. > > + /// > > + /// @return > > + /// \b true if the rewrite was successful, \b false otherwise. > > + //------------------------------------------------------------------ > > + virtual bool > > + RewriteExpression(DiagnosticManager &diagnostic_manager) > > + { > > + return false; > > + } > > > > //------------------------------------------------------------------ > > /// Ready an already-parsed expression for execution, possibly > > > > Modified: lldb/trunk/include/lldb/Target/Target.h > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/include/lldb/Target/Target.h (original) > > +++ lldb/trunk/include/lldb/Target/Target.h Thu Mar 24 20:57:14 2016 > > @@ -149,6 +149,9 @@ public: > > GetEnableAutoImportClangModules () const; > > > > bool > > + GetEnableAutoApplyFixIts () const; > > + > > + bool > > GetEnableSyntheticValue () const; > > > > uint32_t > > @@ -271,6 +274,7 @@ public: > > m_trap_exceptions (true), > > m_generate_debug_info (false), > > m_result_is_internal (false), > > + m_auto_apply_fixits (true), > > m_use_dynamic (lldb::eNoDynamicValues), > > m_timeout_usec (default_timeout), > > m_one_thread_timeout_usec (0), > > @@ -541,6 +545,18 @@ public: > > { > > return m_result_is_internal; > > } > > + > > + void > > + SetAutoApplyFixIts(bool b) > > + { > > + m_auto_apply_fixits = b; > > + } > > + > > + bool > > + GetAutoApplyFixIts() const > > + { > > + return m_auto_apply_fixits; > > + } > > > > private: > > ExecutionPolicy m_execution_policy; > > @@ -558,6 +574,7 @@ private: > > bool m_generate_debug_info; > > bool m_ansi_color_errors; > > bool m_result_is_internal; > > + bool m_auto_apply_fixits; > > lldb::DynamicValueType m_use_dynamic; > > uint32_t m_timeout_usec; > > uint32_t m_one_thread_timeout_usec; > > > > Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) > > +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Thu Mar 24 20:57:14 2016 > > @@ -2347,6 +2347,7 @@ > > 4C2479BE1BA39843009C9A7B /* ExpressionParser.h */ = {isa > = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = > ExpressionParser.h; path = include/lldb/Expression/ExpressionParser.h; > sourceTree = "<group>"; }; > > 4C29E77D1BA2403F00DFF855 /* ExpressionTypeSystemHelper.h > */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; name = > ExpressionTypeSystemHelper.h; path = > include/lldb/Expression/ExpressionTypeSystemHelper.h; sourceTree = > "<group>"; }; > > 4C2FAE2E135E3A70001EDE44 /* SharedCluster.h */ = {isa = > PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; > name = SharedCluster.h; path = include/lldb/Utility/SharedCluster.h; > sourceTree = "<group>"; }; > > + 4C3DA2301CA0BFB800CEB1D4 /* ClangDiagnostic.h */ = {isa > = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; > name = ClangDiagnostic.h; path = ExpressionParser/Clang/ClangDiagnostic.h; > sourceTree = "<group>"; }; > > 4C43DEF9110641F300E55CBF /* ThreadPlanShouldStopHere.h > */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = > sourcecode.c.h; name = ThreadPlanShouldStopHere.h; path = > include/lldb/Target/ThreadPlanShouldStopHere.h; sourceTree = "<group>"; }; > > 4C43DEFA110641F300E55CBF /* ThreadPlanShouldStopHere.cpp > */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = > sourcecode.cpp.cpp; name = ThreadPlanShouldStopHere.cpp; path = > source/Target/ThreadPlanShouldStopHere.cpp; sourceTree = "<group>"; }; > > 4C43DF8511069BFD00E55CBF /* ThreadPlanStepInRange.h */ = > {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = > sourcecode.c.h; name = ThreadPlanStepInRange.h; path = > include/lldb/Target/ThreadPlanStepInRange.h; sourceTree = "<group>"; }; > > @@ -5288,6 +5289,7 @@ > > 4984BA0C1B97620B008658D4 /* Clang */ = { > > isa = PBXGroup; > > children = ( > > + 4C3DA2301CA0BFB800CEB1D4 /* > ClangDiagnostic.h */, > > 4C98D3E0118FB98F00E575D0 /* > ClangFunctionCaller.h */, > > 4C98D3DA118FB96F00E575D0 /* > ClangFunctionCaller.cpp */, > > 26BC7DC010F1B79500F91463 /* > ClangExpressionHelper.h */, > > > > Added: > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/Makefile > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/Makefile?rev=264379&view=auto > > > ============================================================================== > > --- > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/Makefile > (added) > > +++ > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/Makefile > Thu Mar 24 20:57:14 2016 > > @@ -0,0 +1,12 @@ > > +LEVEL = ../../make > > + > > +CXX_SOURCES := main.cpp > > + > > +# clang-3.5+ outputs FullDebugInfo by default for Darwin/FreeBSD > > +# targets. Other targets do not, which causes this test to fail. > > +# This flag enables FullDebugInfo for all targets. > > +ifneq (,$(findstring clang,$(CC))) > > + CFLAGS_EXTRAS += -fno-limit-debug-info > > +endif > > + > > +include $(LEVEL)/Makefile.rules > > > > Added: > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py?rev=264379&view=auto > > > ============================================================================== > > --- > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py > (added) > > +++ > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py > Thu Mar 24 20:57:14 2016 > > @@ -0,0 +1,77 @@ > > +""" > > +Test calling an expression with errors that a FixIt can fix. > > +""" > > + > > +from __future__ import print_function > > + > > + > > + > > +import lldb > > +from lldbsuite.test.decorators import * > > +from lldbsuite.test.lldbtest import * > > +from lldbsuite.test import lldbutil > > + > > +class ExprCommandWithFixits(TestBase): > > + > > + mydir = TestBase.compute_mydir(__file__) > > + > > + def setUp(self): > > + # Call super's setUp(). > > + TestBase.setUp(self) > > + > > + self.main_source = "main.cpp" > > + self.main_source_spec = lldb.SBFileSpec (self.main_source) > > + > > + @skipUnlessDarwin > > + def test(self): > > + """Test calling a function that throws and ObjC exception.""" > > + self.build() > > + self.try_expressions() > > + > > + def try_expressions(self): > > + """Test calling expressions with errors that can be fixed by > the FixIts.""" > > + exe_name = "a.out" > > + exe = os.path.join(os.getcwd(), exe_name) > > + > > + target = self.dbg.CreateTarget(exe) > > + self.assertTrue(target, VALID_TARGET) > > + > > + breakpoint = target.BreakpointCreateBySourceRegex('Stop here to > evaluate expressions',self.main_source_spec) > > + self.assertTrue(breakpoint.GetNumLocations() > 0, > VALID_BREAKPOINT) > > + > > + # Launch the process, and do not stop at the entry point. > > + process = target.LaunchSimple (None, None, > self.get_process_working_directory()) > > + > > + self.assertTrue(process, PROCESS_IS_VALID) > > + > > + # Frame #0 should be at our breakpoint. > > + threads = lldbutil.get_threads_stopped_at_breakpoint (process, > breakpoint) > > + > > + self.assertTrue(len(threads) == 1) > > + self.thread = threads[0] > > + > > + options = lldb.SBExpressionOptions() > > + options.SetAutoApplyFixIts(True) > > + > > + frame = self.thread.GetFrameAtIndex(0) > > + > > + # Try with one error: > > + value = frame.EvaluateExpression("my_pointer.first", options) > > + self.assertTrue(value.IsValid()) > > + self.assertTrue(value.GetError().Success()) > > + self.assertTrue(value.GetValueAsUnsigned() == 10) > > + > > + # Try with two errors: > > + two_error_expression = "my_pointer.second->a" > > + value = frame.EvaluateExpression(two_error_expression, options) > > + self.assertTrue(value.IsValid()) > > + self.assertTrue(value.GetError().Success()) > > + self.assertTrue(value.GetValueAsUnsigned() == 20) > > + > > + # Now turn off the fixits, and the expression should fail: > > + options.SetAutoApplyFixIts(False) > > + value = frame.EvaluateExpression("two_error_expression", > options) > > + self.assertTrue(value.IsValid()) > > + self.assertTrue(value.GetError().Fail()) > > + > > + > > > > Added: > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/main.cpp > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/main.cpp?rev=264379&view=auto > > > ============================================================================== > > --- > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/main.cpp > (added) > > +++ > lldb/trunk/packages/Python/lldbsuite/test/expression_command/fixits/main.cpp > Thu Mar 24 20:57:14 2016 > > @@ -0,0 +1,25 @@ > > +#include <stdio.h> > > + > > +struct SubStruct > > +{ > > + int a; > > + int b; > > +}; > > + > > +struct MyStruct > > +{ > > + int first; > > + struct SubStruct second; > > +}; > > + > > +int > > +main() > > +{ > > + struct MyStruct my_struct = {10, {20, 30}}; > > + struct MyStruct *my_pointer = &my_struct; > > + printf ("Stop here to evaluate expressions: %d %d %p\n", > my_pointer->first, my_pointer->second.a, my_pointer); > > + return 0; > > +} > > + > > + > > + > > > > Modified: lldb/trunk/scripts/interface/SBExpressionOptions.i > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/interface/SBExpressionOptions.i?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/scripts/interface/SBExpressionOptions.i (original) > > +++ lldb/trunk/scripts/interface/SBExpressionOptions.i Thu Mar 24 > 20:57:14 2016 > > @@ -118,6 +118,15 @@ public: > > %feature("docstring", "Sets the prefix to use for this expression. > This prefix gets inserted after the 'target.expr-prefix' prefix contents, > but before the wrapped expression function body.") SetPrefix; > > void > > SetPrefix (const char *prefix); > > + > > + %feature("docstring", "Sets whether to auto-apply FixIt hints to > the expression being evaluated.") SetAutoApplyFixIts; > > + void > > + SetAutoApplyFixIts(bool b = true); > > + > > + %feature("docstring", "Gets whether to auto-apply FixIt hints to an > expression.") GetAutoApplyFixIts; > > + bool > > + GetAutoApplyFixIts(); > > + > > > > protected: > > > > > > Modified: lldb/trunk/source/API/SBExpressionOptions.cpp > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBExpressionOptions.cpp?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/source/API/SBExpressionOptions.cpp (original) > > +++ lldb/trunk/source/API/SBExpressionOptions.cpp Thu Mar 24 20:57:14 > 2016 > > @@ -197,6 +197,18 @@ SBExpressionOptions::SetPrefix (const ch > > return m_opaque_ap->SetPrefix(prefix); > > } > > > > +bool > > +SBExpressionOptions::GetAutoApplyFixIts () > > +{ > > + return m_opaque_ap->GetAutoApplyFixIts (); > > +} > > + > > +void > > +SBExpressionOptions::SetAutoApplyFixIts (bool b) > > +{ > > + return m_opaque_ap->SetAutoApplyFixIts (b); > > +} > > + > > EvaluateExpressionOptions * > > SBExpressionOptions::get() const > > { > > > > Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original) > > +++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Thu Mar 24 > 20:57:14 2016 > > @@ -61,6 +61,7 @@ CommandObjectExpression::CommandOptions: > > { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", > 'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, > eArgTypeBoolean, "Clean up program state if the expression causes a > crash, or raises a signal. Note, unlike gdb hitting a breakpoint is > controlled by another option (-i)."}, > > { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", > 'g', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, > "When specified, debug the JIT code by setting a breakpoint on the first > instruction and forcing breakpoints to not be ignored (-i0) and no > unwinding to happen on error (-u0)."}, > > { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", > 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, > eArgTypeLanguage, "Specifies the Language to use when parsing the > expression. If not set the target.language setting is used." }, > > + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", > 'X', OptionParser::eRequiredArgument, nullptr, nullptr, 0, > eArgTypeLanguage, "If true, simple FixIt hints will be automatically > applied to the expression." }, > > { LLDB_OPT_SET_1, false, "description-verbosity", 'v', > OptionParser::eOptionalArgument, nullptr, g_description_verbosity_type, 0, > eArgTypeDescriptionVerbosity, "How verbose should the output of this > expression be, if the object description is asked for."}, > > }; > > > > @@ -149,6 +150,17 @@ CommandObjectExpression::CommandOptions: > > ignore_breakpoints = false; > > break; > > > > + case 'X': > > + { > > + bool success; > > + bool tmp_value = Args::StringToBoolean(option_arg, true, > &success); > > + if (success) > > + auto_apply_fixits = tmp_value ? eLazyBoolYes : > eLazyBoolNo; > > + else > > + error.SetErrorStringWithFormat("could not convert > \"%s\" to a boolean value.", option_arg); > > + break; > > + } > > + > > default: > > error.SetErrorStringWithFormat("invalid short option character > '%c'", short_option); > > break; > > @@ -178,6 +190,7 @@ CommandObjectExpression::CommandOptions: > > debug = false; > > language = eLanguageTypeUnknown; > > m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; > > + auto_apply_fixits = eLazyBoolCalculate; > > } > > > > const OptionDefinition* > > @@ -294,6 +307,14 @@ CommandObjectExpression::EvaluateExpress > > options.SetTryAllThreads(m_command_options.try_all_threads); > > options.SetDebug(m_command_options.debug); > > options.SetLanguage(m_command_options.language); > > + > > + bool auto_apply_fixits; > > + if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) > > + auto_apply_fixits = target->GetEnableAutoApplyFixIts(); > > + else > > + auto_apply_fixits = m_command_options.auto_apply_fixits == > eLazyBoolYes ? true : false; > > + > > + options.SetAutoApplyFixIts(auto_apply_fixits); > > > > // If there is any chance we are going to stop and want to see > > // what went wrong with our expression, we should generate > debug info > > > > Modified: lldb/trunk/source/Commands/CommandObjectExpression.h > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.h?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/source/Commands/CommandObjectExpression.h (original) > > +++ lldb/trunk/source/Commands/CommandObjectExpression.h Thu Mar 24 > 20:57:14 2016 > > @@ -14,13 +14,13 @@ > > // C++ Includes > > // Other libraries and framework includes > > // Project includes > > +#include "lldb/lldb-private-enumerations.h" > > #include "lldb/Core/IOHandler.h" > > #include "lldb/Interpreter/CommandObject.h" > > #include "lldb/Interpreter/OptionGroupBoolean.h" > > #include "lldb/Interpreter/OptionGroupFormat.h" > > #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" > > #include "lldb/Target/ExecutionContext.h" > > - > > namespace lldb_private { > > > > class CommandObjectExpression : > > @@ -63,6 +63,7 @@ public: > > bool try_all_threads; > > lldb::LanguageType language; > > LanguageRuntimeDescriptionDisplayVerbosity m_verbosity; > > + LazyBool auto_apply_fixits; > > }; > > > > CommandObjectExpression (CommandInterpreter &interpreter); > > > > Modified: lldb/trunk/source/Expression/DiagnosticManager.cpp > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/DiagnosticManager.cpp?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/source/Expression/DiagnosticManager.cpp (original) > > +++ lldb/trunk/source/Expression/DiagnosticManager.cpp Thu Mar 24 > 20:57:14 2016 > > @@ -52,10 +52,10 @@ DiagnosticManager::GetString(char separa > > { > > std::string ret; > > > > - for (const Diagnostic &diagnostic : Diagnostics()) > > + for (const Diagnostic *diagnostic : Diagnostics()) > > { > > - ret.append(StringForSeverity(diagnostic.severity)); > > - ret.append(diagnostic.message); > > + ret.append(StringForSeverity(diagnostic->GetSeverity())); > > + ret.append(diagnostic->GetMessage()); > > ret.push_back(separator); > > } > > > > > > Modified: lldb/trunk/source/Expression/UserExpression.cpp > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/UserExpression.cpp?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/source/Expression/UserExpression.cpp (original) > > +++ lldb/trunk/source/Expression/UserExpression.cpp Thu Mar 24 20:57:14 > 2016 > > @@ -253,6 +253,7 @@ UserExpression::Evaluate (ExecutionConte > > } > > > > 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)) > > > > Added: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h?rev=264379&view=auto > > > ============================================================================== > > --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h > (added) > > +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h > Thu Mar 24 20:57:14 2016 > > @@ -0,0 +1,59 @@ > > +//===-- DiagnosticManager.h -------------------------------------*- C++ > -*-===// > > +// > > +// The LLVM Compiler Infrastructure > > +// > > +// This file is distributed under the University of Illinois Open Source > > +// License. See LICENSE.TXT for details. > > +// > > > +//===----------------------------------------------------------------------===// > > + > > +#ifndef lldb_ClangDiagnostic_h > > +#define lldb_ClangDiagnostic_h > > + > > +#include <vector> > > + > > +#include "clang/Basic/Diagnostic.h" > > + > > +#include "lldb/lldb-defines.h" > > +#include "lldb/lldb-types.h" > > + > > +#include "lldb/Expression/DiagnosticManager.h" > > + > > +namespace lldb_private > > +{ > > + > > +typedef std::vector<clang::FixItHint> FixItList; > > + > > +class ClangDiagnostic : public Diagnostic > > +{ > > +public: > > + static inline bool classof(const ClangDiagnostic *) { return true; } > > + static inline bool classof(const Diagnostic *diag) { > > + return diag->getKind() == eDiagnosticOriginClang; > > + } > > + > > + ClangDiagnostic(const char *message, DiagnosticSeverity severity, > uint32_t compiler_id) : > > + Diagnostic(message, severity, eDiagnosticOriginClang, > compiler_id) > > + { > > + } > > + > > + virtual ~ClangDiagnostic() = default; > > + > > + bool HasFixIts () const override { return !m_fixit_vec.empty(); } > > + > > + void > > + AddFixitHint (const clang::FixItHint &fixit) > > + { > > + m_fixit_vec.push_back(fixit); > > + } > > + > > + const FixItList & > > + FixIts() const > > + { > > + return m_fixit_vec; > > + } > > + FixItList m_fixit_vec; > > +}; > > + > > +} // namespace lldb_private > > +#endif /* lldb_ClangDiagnostic_h */ > > > > Modified: > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp > (original) > > +++ > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp > Thu Mar 24 20:57:14 2016 > > @@ -17,9 +17,12 @@ > > #include "clang/Basic/FileManager.h" > > #include "clang/Basic/SourceLocation.h" > > #include "clang/Basic/TargetInfo.h" > > -#include "clang/Basic/Version.h" > > +#include "clang/Basic/Version.h" > > #include "clang/CodeGen/CodeGenAction.h" > > #include "clang/CodeGen/ModuleBuilder.h" > > +#include "clang/Edit/Commit.h" > > +#include "clang/Edit/EditsReceiver.h" > > +#include "clang/Edit/EditedSource.h" > > #include "clang/Frontend/CompilerInstance.h" > > #include "clang/Frontend/CompilerInvocation.h" > > #include "clang/Frontend/FrontendActions.h" > > @@ -30,6 +33,7 @@ > > #include "clang/Lex/Preprocessor.h" > > #include "clang/Parse/ParseAST.h" > > #include "clang/Rewrite/Frontend/FrontendActions.h" > > +#include "clang/Rewrite/Core/Rewriter.h" > > #include "clang/Sema/SemaConsumer.h" > > #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" > > > > @@ -54,6 +58,7 @@ > > > > // Project includes > > #include "ClangExpressionParser.h" > > +#include "ClangDiagnostic.h" > > > > #include "ClangASTSource.h" > > #include "ClangExpressionHelper.h" > > @@ -175,24 +180,48 @@ public: > > diag_str.push_back('\0'); > > const char *data = diag_str.data(); > > > > + DiagnosticSeverity severity; > > + bool make_new_diagnostic = true; > > + > > switch (DiagLevel) > > { > > case DiagnosticsEngine::Level::Fatal: > > case DiagnosticsEngine::Level::Error: > > - m_manager->AddDiagnostic(data, > eDiagnosticSeverityError, eDiagnosticOriginClang, Info.getID()); > > + severity = eDiagnosticSeverityError; > > break; > > case DiagnosticsEngine::Level::Warning: > > - m_manager->AddDiagnostic(data, > eDiagnosticSeverityWarning, eDiagnosticOriginClang, Info.getID()); > > + severity = eDiagnosticSeverityWarning; > > break; > > case DiagnosticsEngine::Level::Remark: > > case DiagnosticsEngine::Level::Ignored: > > - m_manager->AddDiagnostic(data, > eDiagnosticSeverityRemark, eDiagnosticOriginClang, Info.getID()); > > + severity = eDiagnosticSeverityRemark; > > break; > > case DiagnosticsEngine::Level::Note: > > m_manager->AppendMessageToDiagnostic(data); > > + make_new_diagnostic = false; > > + } > > + if (make_new_diagnostic) > > + { > > + ClangDiagnostic *new_diagnostic = new > ClangDiagnostic(data, severity, Info.getID()); > > + m_manager->AddDiagnostic(new_diagnostic); > > + > > + // Don't store away warning fixits, since the compiler > doesn't have enough > > + // context in an expression for the warning to be > useful. > > + // FIXME: Should we try to filter out FixIts that apply > to our generated > > + // code, and not the user's expression? > > + if (severity == eDiagnosticSeverityError) > > + { > > + size_t num_fixit_hints = Info.getNumFixItHints(); > > + for (int i = 0; i < num_fixit_hints; i++) > > + { > > + const clang::FixItHint &fixit = > Info.getFixItHint(i); > > + if (!fixit.isNull()) > > + new_diagnostic->AddFixitHint(fixit); > > + } > > + } > > } > > } > > - > > + > > m_passthrough->HandleDiagnostic(DiagLevel, Info); > > } > > > > @@ -666,6 +695,87 @@ ClangExpressionParser::Parse(DiagnosticM > > return num_errors; > > } > > > > +bool > > +ClangExpressionParser::RewriteExpression(DiagnosticManager > &diagnostic_manager) > > +{ > > + clang::SourceManager &source_manager = > m_compiler->getSourceManager(); > > + clang::edit::EditedSource editor(source_manager, > m_compiler->getLangOpts(), nullptr); > > + clang::edit::Commit commit(editor); > > + clang::Rewriter rewriter(source_manager, m_compiler->getLangOpts()); > > + > > + class RewritesReceiver : public edit::EditsReceiver { > > + Rewriter &rewrite; > > + > > + public: > > + RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) { } > > + > > + void insert(SourceLocation loc, StringRef text) override { > > + rewrite.InsertText(loc, text); > > + } > > + void replace(CharSourceRange range, StringRef text) override { > > + rewrite.ReplaceText(range.getBegin(), > rewrite.getRangeSize(range), text); > > + } > > + }; > > + > > + RewritesReceiver rewrites_receiver(rewriter); > > + > > + const DiagnosticList &diagnostics = > diagnostic_manager.Diagnostics(); > > + size_t num_diags = diagnostics.size(); > > + if (num_diags == 0) > > + return false; > > + > > + for (const Diagnostic *diag : diagnostic_manager.Diagnostics()) > > + { > > + const ClangDiagnostic *diagnostic = > llvm::dyn_cast<ClangDiagnostic>(diag); > > + if (diagnostic && diagnostic->HasFixIts()) > > + { > > + for (const FixItHint &fixit : diagnostic->FixIts()) > > + { > > + // This is cobbed from clang::Rewrite::FixItRewriter. > > + if (fixit.CodeToInsert.empty()) > > + { > > + if (fixit.InsertFromRange.isValid()) > > + { > > + > commit.insertFromRange(fixit.RemoveRange.getBegin(), > > + fixit.InsertFromRange, > /*afterToken=*/false, > > + > fixit.BeforePreviousInsertions); > > + } > > + else > > + commit.remove(fixit.RemoveRange); > > + } > > + else > > + { > > + if (fixit.RemoveRange.isTokenRange() || > > + fixit.RemoveRange.getBegin() != > fixit.RemoveRange.getEnd()) > > + commit.replace(fixit.RemoveRange, > fixit.CodeToInsert); > > + else > > + commit.insert(fixit.RemoveRange.getBegin(), > fixit.CodeToInsert, > > + /*afterToken=*/false, > fixit.BeforePreviousInsertions); > > + } > > + } > > + } > > + } > > + > > + // FIXME - do we want to try to propagate specific errors here? > > + if (!commit.isCommitable()) > > + return false; > > + else if (!editor.commit(commit)) > > + return false; > > + > > + // Now play all the edits, and stash the result in the diagnostic > manager. > > + editor.applyRewrites(rewrites_receiver); > > + RewriteBuffer &main_file_buffer = > rewriter.getEditBuffer(source_manager.getMainFileID()); > > + > > + std::string fixed_expression; > > + llvm::raw_string_ostream out_stream(fixed_expression); > > + > > + main_file_buffer.write(out_stream); > > + out_stream.flush(); > > + diagnostic_manager.SetFixedExpression(fixed_expression); > > + > > + return true; > > +} > > + > > static bool FindFunctionInModule (ConstString &mangled_name, > > llvm::Module *module, > > const char *orig_name) > > > > Modified: > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h > (original) > > +++ > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h > Thu Mar 24 20:57:14 2016 > > @@ -73,6 +73,9 @@ public: > > //------------------------------------------------------------------ > > unsigned > > Parse(DiagnosticManager &diagnostic_manager) override; > > + > > + bool > > + RewriteExpression(DiagnosticManager &diagnostic_manager) override; > > > > //------------------------------------------------------------------ > > /// Ready an already-parsed expression for execution, possibly > > > > Modified: > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp > (original) > > +++ > lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp > Thu Mar 24 20:57:14 2016 > > @@ -23,6 +23,7 @@ > > #include "ClangExpressionParser.h" > > #include "ClangModulesDeclVendor.h" > > #include "ClangPersistentVariables.h" > > +#include "ClangDiagnostic.h" > > > > #include "lldb/Core/ConstString.h" > > #include "lldb/Core/Log.h" > > @@ -358,8 +359,6 @@ ClangUserExpression::Parse(DiagnosticMan > > diagnostic_manager.PutCString(eDiagnosticSeverityWarning, > err.AsCString()); > > } > > > > - StreamString m_transformed_stream; > > - > > //////////////////////////////////// > > // Generate the expression > > // > > @@ -489,10 +488,38 @@ ClangUserExpression::Parse(DiagnosticMan > > if (!exe_scope) > > exe_scope = exe_ctx.GetTargetPtr(); > > > > - ClangExpressionParser parser(exe_scope, *this, generate_debug_info); > > + // We use a shared pointer here so we can use the original parser - > if it succeeds > > + // or the rewrite parser we might make if it fails. But the > parser_sp will never be empty. > > + > > + std::shared_ptr<ClangExpressionParser> parser_sp(new > ClangExpressionParser(exe_scope, *this, generate_debug_info)); > > > > - unsigned num_errors = parser.Parse(diagnostic_manager); > > + unsigned num_errors = parser_sp->Parse(diagnostic_manager); > > > > + // Check here for FixItHints. If there are any try fixing the > source and re-parsing... > > + if (num_errors && diagnostic_manager.HasFixIts() && > diagnostic_manager.ShouldAutoApplyFixIts()) > > + { > > + if (parser_sp->RewriteExpression(diagnostic_manager)) > > + { > > + std::string backup_source = std::move(m_transformed_text); > > + m_transformed_text = > diagnostic_manager.GetFixedExpression(); > > + // Make a new diagnostic manager and parser, and try again > with the rewritten expression: > > + // FIXME: It would be nice to reuse the parser we have but > that doesn't seem to be possible. > > + DiagnosticManager rewrite_manager; > > + std::shared_ptr<ClangExpressionParser> > rewrite_parser_sp(new ClangExpressionParser(exe_scope, *this, > generate_debug_info)); > > + unsigned rewrite_errors = > rewrite_parser_sp->Parse(rewrite_manager); > > + if (rewrite_errors == 0) > > + { > > + diagnostic_manager.Clear(); > > + parser_sp = rewrite_parser_sp; > > + num_errors = 0; > > + } > > + else > > + { > > + m_transformed_text = std::move(backup_source); > > + } > > + } > > + } > > + > > if (num_errors) > > { > > diagnostic_manager.Printf(eDiagnosticSeverityError, "%u error%s > parsing expression", num_errors, > > @@ -508,8 +535,12 @@ ClangUserExpression::Parse(DiagnosticMan > > // > > > > { > > - Error jit_error = parser.PrepareForExecution(m_jit_start_addr, > m_jit_end_addr, m_execution_unit_sp, exe_ctx, > > - m_can_interpret, > execution_policy); > > + Error jit_error = > parser_sp->PrepareForExecution(m_jit_start_addr, > > + m_jit_end_addr, > > + > m_execution_unit_sp, > > + exe_ctx, > > + > m_can_interpret, > > + > execution_policy); > > > > if (!jit_error.Success()) > > { > > @@ -524,7 +555,7 @@ ClangUserExpression::Parse(DiagnosticMan > > > > if (exe_ctx.GetProcessPtr() && execution_policy == > eExecutionPolicyTopLevel) > > { > > - Error static_init_error = > parser.RunStaticInitializers(m_execution_unit_sp, exe_ctx); > > + Error static_init_error = > parser_sp->RunStaticInitializers(m_execution_unit_sp, exe_ctx); > > > > if (!static_init_error.Success()) > > { > > > > Modified: lldb/trunk/source/Target/Target.cpp > > URL: > http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=264379&r1=264378&r2=264379&view=diff > > > ============================================================================== > > --- lldb/trunk/source/Target/Target.cpp (original) > > +++ lldb/trunk/source/Target/Target.cpp Thu Mar 24 20:57:14 2016 > > @@ -3425,6 +3425,7 @@ g_properties[] = > > { "debug-file-search-paths" , > OptionValue::eTypeFileSpecList, false, 0 , nullptr, > nullptr, "List of directories to be searched when locating debug symbol > files." }, > > { "clang-module-search-paths" , > OptionValue::eTypeFileSpecList, false, 0 , nullptr, > nullptr, "List of directories to be searched when locating modules for > Clang." }, > > { "auto-import-clang-modules" , OptionValue::eTypeBoolean > , false, true , nullptr, nullptr, "Automatically load > Clang modules referred to by the program." }, > > + { "auto-apply-fixits" , OptionValue::eTypeBoolean > , false, true , nullptr, nullptr, "Automatically > apply fixit hints to expressions." }, > > { "max-children-count" , OptionValue::eTypeSInt64 > , false, 256 , nullptr, nullptr, "Maximum number of > children to expand in any level of depth." }, > > { "max-string-summary-length" , OptionValue::eTypeSInt64 > , false, 1024 , nullptr, nullptr, "Maximum number of > characters to show when using %s in summary strings." }, > > { "max-memory-read-size" , OptionValue::eTypeSInt64 > , false, 1024 , nullptr, nullptr, "Maximum number of > bytes that 'memory read' will fetch before --force must be specified." }, > > @@ -3481,6 +3482,7 @@ enum > > ePropertyDebugFileSearchPaths, > > ePropertyClangModuleSearchPaths, > > ePropertyAutoImportClangModules, > > + ePropertyAutoApplyFixIts, > > ePropertyMaxChildrenCount, > > ePropertyMaxSummaryLength, > > ePropertyMaxMemReadSize, > > @@ -3853,6 +3855,13 @@ TargetProperties::GetEnableAutoImportCla > > return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, > g_properties[idx].default_uint_value != 0); > > } > > > > +bool > > +TargetProperties::GetEnableAutoApplyFixIts() const > > +{ > > + const uint32_t idx = ePropertyAutoApplyFixIts; > > + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, > g_properties[idx].default_uint_value != 0); > > +} > > + > > bool > > TargetProperties::GetEnableSyntheticValue () const > > { > > > > > > _______________________________________________ > > lldb-commits mailing list > > lldb-commits@lists.llvm.org > > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits > > _______________________________________________ > > lldb-commits mailing list > > lldb-commits@lists.llvm.org > > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits > >
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits