Index: include/lldb/Target/Target.h =================================================================== --- include/lldb/Target/Target.h +++ include/lldb/Target/Target.h @@ -172,6 +172,9 @@ lldb::LanguageType GetLanguage () const; + bool + GetLanguageFollowsFrame () const; + const char * GetExpressionPrefixContentsAsCString (); @@ -1437,6 +1440,9 @@ m_platform_sp = platform_sp; } + lldb::LanguageType + GetLanguageOfSelectedFrame () const; + SourceManager & GetSourceManager (); Index: source/Commands/CommandObjectExpression.cpp =================================================================== --- source/Commands/CommandObjectExpression.cpp +++ source/Commands/CommandObjectExpression.cpp @@ -300,12 +300,16 @@ options.SetUseDynamic(m_varobj_options.use_dynamic); options.SetTryAllThreads(m_command_options.try_all_threads); options.SetDebug(m_command_options.debug); - - // If the language was not specified, set it from target's properties + + // If the expression's language was not specified, check the + // target's properties to see if a language override was set, + // or if the language should match that of the frame. if (m_command_options.language != eLanguageTypeUnknown) options.SetLanguage(m_command_options.language); - else + else if (target->GetLanguage() != eLanguageTypeUnknown) options.SetLanguage(target->GetLanguage()); + else if (target->GetLanguageFollowsFrame()) + options.SetLanguage(target->GetLanguageOfSelectedFrame()); // 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 Index: source/Target/Target.cpp =================================================================== --- source/Target/Target.cpp +++ source/Target/Target.cpp @@ -43,6 +43,7 @@ #include "lldb/Interpreter/OptionValues.h" #include "lldb/Interpreter/Property.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/ObjCLanguageRuntime.h" @@ -383,8 +384,15 @@ if (skip_prologue == eLazyBoolCalculate) skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo; + + // If breakpoint's language wasn't set, use target's. if (language == lldb::eLanguageTypeUnknown) language = GetLanguage(); + // If the target's language override wasn't set but + // was set to follow the selected frame, use that. + if (language == lldb::eLanguageTypeUnknown && + GetLanguageFollowsFrame()) + language = GetLanguageOfSelectedFrame(); BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL, func_name, @@ -415,8 +423,15 @@ if (skip_prologue == eLazyBoolCalculate) skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo; + + // If breakpoint's language wasn't set, use target's. if (language == lldb::eLanguageTypeUnknown) language = GetLanguage(); + // If the target's language override wasn't set but + // was set to follow the selected frame, use that. + if (language == lldb::eLanguageTypeUnknown && + GetLanguageFollowsFrame()) + language = GetLanguageOfSelectedFrame(); BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL, func_names, @@ -446,9 +461,15 @@ if (skip_prologue == eLazyBoolCalculate) skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo; + + // If breakpoint's language wasn't set, use target's. if (language == lldb::eLanguageTypeUnknown) language = GetLanguage(); - + // If the target's language override wasn't set but + // was set to follow the selected frame, use that. + if (language == lldb::eLanguageTypeUnknown && + GetLanguageFollowsFrame()) + language = GetLanguageOfSelectedFrame(); BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL, func_names, @@ -2134,6 +2155,28 @@ return opcode_addr; } +// Return the language of the selected frame's CU. +lldb::LanguageType +Target::GetLanguageOfSelectedFrame () const +{ + LanguageType language = eLanguageTypeUnknown; + if (m_process_sp) + { + ThreadSP sel_thread_sp(m_process_sp->GetThreadList().GetSelectedThread()); + if (sel_thread_sp) + { + StackFrameSP sel_frame_sp = sel_thread_sp->GetSelectedFrame(); + if (sel_frame_sp) + { + CompileUnit *cu = sel_frame_sp->GetSymbolContext(eSymbolContextCompUnit).comp_unit; + if (cu) + language = cu->GetLanguage(); + } + } + } + return language; +} + SourceManager & Target::GetSourceManager () { @@ -2951,7 +2994,8 @@ { { "default-arch" , OptionValue::eTypeArch , true , 0 , NULL, NULL, "Default architecture to choose, when there's a choice." }, { "move-to-nearest-code" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Move breakpoints to nearest code." }, - { "language" , OptionValue::eTypeLanguage , false, eLanguageTypeUnknown , NULL, NULL, "The language to use when interpreting expressions entered in commands (note: currently only implemented for breakpoints identifiers)." }, + { "language" , OptionValue::eTypeLanguage , false, eLanguageTypeUnknown , NULL, NULL, "The language to use when interpreting expressions entered in commands." }, + { "language-follows-frame" , OptionValue::eTypeBoolean , false, false , NULL, NULL, "If the target.language is unknown, default to the language of the selected frame." }, { "expr-prefix" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "Path to a file containing expressions to be prepended to all expressions." }, { "prefer-dynamic-value" , OptionValue::eTypeEnum , false, eDynamicDontRunTarget , NULL, g_dynamic_value_types, "Should printed values be shown as their dynamic value." }, { "enable-synthetic-value" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Should synthetic values be used by default whenever available." }, @@ -3011,6 +3055,7 @@ ePropertyDefaultArch, ePropertyMoveToNearestCode, ePropertyLanguage, + ePropertyLanguageFollowsFrame, ePropertyExprPrefix, ePropertyPreferDynamic, ePropertyEnableSynthetic, @@ -3468,6 +3513,13 @@ return LanguageType(); } +bool +TargetProperties::GetLanguageFollowsFrame () const +{ + const uint32_t idx = ePropertyLanguageFollowsFrame; + return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); +} + const char * TargetProperties::GetExpressionPrefixContentsAsCString () { Index: test/expression_command/options/main.cpp =================================================================== --- test/expression_command/options/main.cpp +++ test/expression_command/options/main.cpp @@ -10,7 +10,6 @@ int main (int argc, char const *argv[]) { - // breakpoint_in_main - bar(); + bar(); // breakpoint_in_main return foo(); } Index: test/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py =================================================================== --- test/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py +++ test/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py @@ -75,13 +75,23 @@ exe = os.path.join(os.getcwd(), "a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) - # This should create a breakpoint with 1 locations. + # This should create a breakpoint with 1 location. + lldbutil.run_break_set_by_symbol (self, 'ns::func', sym_exact=False, extra_options = "-L c++", num_expected_locations=1) + # The language of the frame's CU is unknwon, so C++ is on by + # default. Hence this should create a breakpoint with 1 location. + self.runCmd("settings set target.language-follows-frame true") lldbutil.run_break_set_by_symbol (self, 'ns::func', sym_exact=False, extra_options = "-L c++", num_expected_locations=1) + self.runCmd("settings clear target.language-follows-frame") # This should create a breakpoint with 0 locations. lldbutil.run_break_set_by_symbol (self, 'ns::func', sym_exact=False, extra_options = "-L c", num_expected_locations=0) self.runCmd("settings set target.language c") lldbutil.run_break_set_by_symbol (self, 'ns::func', sym_exact=False, num_expected_locations=0) + # target.language overrides target.language-follows-frame, + # so this should also create a breakpoint with 0 locations. + self.runCmd("settings set target.language-follows-frame true") + lldbutil.run_break_set_by_symbol (self, 'ns::func', sym_exact=False, num_expected_locations=0) + self.runCmd("settings clear target.language-follows-frame") # Run the program. self.runCmd("run", RUN_SUCCEEDED)