diff options
-rw-r--r-- | lldb/include/lldb/Expression/ASTResultSynthesizer.h | 6 | ||||
-rw-r--r-- | lldb/include/lldb/Expression/ClangExpression.h | 15 | ||||
-rw-r--r-- | lldb/include/lldb/Expression/ClangUserExpression.h | 32 | ||||
-rw-r--r-- | lldb/include/lldb/Target/Target.h | 1 | ||||
-rw-r--r-- | lldb/scripts/clang.DebuggerCastResultToId.diff | 25 | ||||
-rw-r--r-- | lldb/source/API/SBFrame.cpp | 2 | ||||
-rw-r--r-- | lldb/source/API/SBValue.cpp | 1 | ||||
-rw-r--r-- | lldb/source/Breakpoint/BreakpointOptions.cpp | 12 | ||||
-rw-r--r-- | lldb/source/Breakpoint/Watchpoint.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectExpression.cpp | 1 | ||||
-rw-r--r-- | lldb/source/Expression/ASTResultSynthesizer.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionParser.cpp | 3 | ||||
-rw-r--r-- | lldb/source/Expression/ClangUserExpression.cpp | 19 | ||||
-rw-r--r-- | lldb/source/Interpreter/CommandInterpreter.cpp | 5 | ||||
-rw-r--r-- | lldb/source/Target/Process.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Target/StopInfo.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Target/Target.cpp | 2 | ||||
-rw-r--r-- | lldb/test/lang/objc/foundation/TestObjCMethods2.py | 28 |
18 files changed, 125 insertions, 39 deletions
diff --git a/lldb/include/lldb/Expression/ASTResultSynthesizer.h b/lldb/include/lldb/Expression/ASTResultSynthesizer.h index 2b5cac1e387..79709de3546 100644 --- a/lldb/include/lldb/Expression/ASTResultSynthesizer.h +++ b/lldb/include/lldb/Expression/ASTResultSynthesizer.h @@ -41,16 +41,11 @@ public: /// pass to the next step in the chain after processing. Passthrough is /// the next ASTConsumer, or NULL if none is required. /// - /// @param[in] desired_type - /// The type that the result should have. May be initialized with a - /// NULL type, in which case the type is inferred. - /// /// @param[in] target /// The target, which contains the persistent variable store and the /// AST importer. //---------------------------------------------------------------------- ASTResultSynthesizer(clang::ASTConsumer *passthrough, - TypeFromUser desired_type, Target &target); //---------------------------------------------------------------------- @@ -182,7 +177,6 @@ private: clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer. Target &m_target; ///< The target, which contains the persistent variable store and the clang::Sema *m_sema; ///< The Sema to use. - TypeFromUser m_desired_type; ///< If non-NULL, the type to coerce the result to. }; } diff --git a/lldb/include/lldb/Expression/ClangExpression.h b/lldb/include/lldb/Expression/ClangExpression.h index 435e7c7811d..b870dae07c6 100644 --- a/lldb/include/lldb/Expression/ClangExpression.h +++ b/lldb/include/lldb/Expression/ClangExpression.h @@ -41,6 +41,11 @@ class RecordingMemoryManager; class ClangExpression { public: + enum ResultType { + eResultTypeAny, + eResultTypeId + }; + ClangExpression () : m_jit_process_sp(), m_jit_alloc (LLDB_INVALID_ADDRESS), @@ -108,6 +113,16 @@ public: ASTTransformer (clang::ASTConsumer *passthrough) = 0; //------------------------------------------------------------------ + /// Return the desired result type of the function, or + /// eResultTypeAny if indifferent. + //------------------------------------------------------------------ + virtual ResultType + DesiredResultType () + { + return eResultTypeAny; + } + + //------------------------------------------------------------------ /// Flags //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Expression/ClangUserExpression.h b/lldb/include/lldb/Expression/ClangUserExpression.h index 6ce1c374d63..9e0080312b1 100644 --- a/lldb/include/lldb/Expression/ClangUserExpression.h +++ b/lldb/include/lldb/Expression/ClangUserExpression.h @@ -48,7 +48,7 @@ class ClangUserExpression : public ClangExpression { public: typedef lldb::SharedPtr<ClangUserExpression>::Type ClangUserExpressionSP; - + //------------------------------------------------------------------ /// Constructor /// @@ -63,10 +63,15 @@ public: /// If not eLanguageTypeUnknown, a language to use when parsing /// the expression. Currently restricted to those languages /// supported by Clang. + /// + /// @param[in] desired_type + /// If not eResultTypeAny, the type to use for the expression + /// result. //------------------------------------------------------------------ ClangUserExpression (const char *expr, const char *expr_prefix, - lldb::LanguageType language); + lldb::LanguageType language, + ResultType desired_type); //------------------------------------------------------------------ /// Destructor @@ -85,10 +90,6 @@ public: /// are needed for parsing (locations of functions, types of /// variables, persistent variables, etc.) /// - /// @param[in] desired_type - /// The type that the expression should be coerced to. If NULL, - /// inferred from the expression itself. - /// /// @param[in] execution_policy /// Determines whether interpretation is possible or mandatory. /// @@ -102,7 +103,6 @@ public: bool Parse (Stream &error_stream, ExecutionContext &exe_ctx, - TypeFromUser desired_type, lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory); @@ -247,6 +247,16 @@ public: ASTTransformer (clang::ASTConsumer *passthrough); //------------------------------------------------------------------ + /// Return the desired result type of the function, or + /// eResultTypeAny if indifferent. + //------------------------------------------------------------------ + virtual ResultType + DesiredResultType () + { + return m_desired_type; + } + + //------------------------------------------------------------------ /// Return true if validation code should be inserted into the /// expression. //------------------------------------------------------------------ @@ -285,6 +295,10 @@ public: /// True if the thread's state should be restored in the case /// of an error. /// + /// @param[in] result_type + /// If not eResultTypeAny, the type of the desired result. Will + /// result in parse errors if impossible. + /// /// @param[in] expr_cstr /// A C string containing the expression to be evaluated. /// @@ -302,6 +316,7 @@ public: 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, @@ -311,6 +326,7 @@ public: 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, @@ -346,7 +362,7 @@ private: bool m_allow_cxx; ///< True if the language allows C++. bool m_allow_objc; ///< True if the language allows Objective-C. std::string m_transformed_text; ///< The text of the expression, as send to the parser - TypeFromUser m_desired_type; ///< The type to coerce the expression's result to. If NULL, inferred from the expression. + ResultType m_desired_type; ///< The type to coerce the expression's result to. If eResultTypeAny, inferred from the expression. std::auto_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression. std::auto_ptr<ClangExpressionVariableList> m_local_variables; ///< The local expression variables, if the expression is DWARF. diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 70ed0434c6c..a202fb8ee6c 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -816,6 +816,7 @@ public: EvaluateExpression (const char *expression, StackFrame *frame, lldb_private::ExecutionPolicy execution_policy, + bool coerce_to_id, bool unwind_on_error, bool keep_in_memory, lldb::DynamicValueType use_dynamic, diff --git a/lldb/scripts/clang.DebuggerCastResultToId.diff b/lldb/scripts/clang.DebuggerCastResultToId.diff new file mode 100644 index 00000000000..01fe8a2f064 --- /dev/null +++ b/lldb/scripts/clang.DebuggerCastResultToId.diff @@ -0,0 +1,25 @@ +Index: include/clang/Basic/LangOptions.def +=================================================================== +--- include/clang/Basic/LangOptions.def (revision 146622) ++++ include/clang/Basic/LangOptions.def (working copy) +@@ -121,6 +121,7 @@ + BENIGN_LANGOPT(InlineVisibilityHidden , 1, 0, "hidden default visibility for inline C++ methods") + BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype") + BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support") ++BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast the result to id if it is of unknown type") + BENIGN_LANGOPT(AddressSanitizer , 1, 0, "AddressSanitizer enabled") + + BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking") +Index: lib/Sema/SemaExprCXX.cpp +=================================================================== +--- lib/Sema/SemaExprCXX.cpp (revision 146622) ++++ lib/Sema/SemaExprCXX.cpp (working copy) +@@ -4675,7 +4675,7 @@ + return ExprError(); + + // Top-level message sends default to 'id' when we're in a debugger. +- if (getLangOptions().DebuggerSupport && ++ if (getLangOptions().DebuggerCastResultToId && + FullExpr.get()->getType() == Context.UnknownAnyTy && + isa<ObjCMessageExpr>(FullExpr.get())) { + FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType()); diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index a541047e9ad..3a3c5823827 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -756,12 +756,14 @@ SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dyna 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/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index 654336db8c5..1ed3fea133a 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -388,6 +388,7 @@ SBValue::CreateValueFromExpression (const char *name, const char* expression) 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/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp index c2277dbc910..79ffa32e3a2 100644 --- a/lldb/source/Breakpoint/BreakpointOptions.cpp +++ b/lldb/source/Breakpoint/BreakpointOptions.cpp @@ -60,7 +60,7 @@ BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) : 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 @@ BreakpointOptions::operator=(const BreakpointOptions& rhs) 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 @@ BreakpointOptions::SetCondition (const char *condition) } 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 @@ BreakpointOptions::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, 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/lldb/source/Breakpoint/Watchpoint.cpp b/lldb/source/Breakpoint/Watchpoint.cpp index 4645b6072e0..e9b314b24ac 100644 --- a/lldb/source/Breakpoint/Watchpoint.cpp +++ b/lldb/source/Breakpoint/Watchpoint.cpp @@ -212,7 +212,7 @@ Watchpoint::SetCondition (const char *condition) 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/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 5134b28b08d..e2ce4b2cf89 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -312,6 +312,7 @@ CommandObjectExpression::EvaluateExpression 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/lldb/source/Expression/ASTResultSynthesizer.cpp b/lldb/source/Expression/ASTResultSynthesizer.cpp index 0df2a5ec690..de17ebd792a 100644 --- a/lldb/source/Expression/ASTResultSynthesizer.cpp +++ b/lldb/source/Expression/ASTResultSynthesizer.cpp @@ -30,14 +30,12 @@ using namespace clang; 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/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp index 351c4847170..912822399dc 100644 --- a/lldb/source/Expression/ClangExpressionParser.cpp +++ b/lldb/source/Expression/ClangExpressionParser.cpp @@ -245,7 +245,10 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, 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/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp index 8f011c089d9..c2164c80037 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Expression/ClangUserExpression.cpp @@ -45,13 +45,14 @@ using namespace lldb_private; 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 @@ ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough) 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 @@ ApplyUnicharHack(std::string &expr) 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 @@ ClangUserExpression::Parse (Stream &error_stream, ////////////////////////// // 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 @@ ExecutionResults 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 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx, 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 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx, 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/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index bce32beb6f1..77cab233b7a 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -1112,13 +1112,16 @@ CommandInterpreter::PreprocessCommand (std::string &command) 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/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index fdd6b1753c7..50bcb7a952a 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1328,7 +1328,7 @@ Process::LoadImage (const FileSpec &image_spec, Error &error) 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 @@ Process::UnloadImage (uint32_t image_token) 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/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp index f90968fdad7..00c76802922 100644 --- a/lldb/source/Target/StopInfo.cpp +++ b/lldb/source/Target/StopInfo.cpp @@ -225,6 +225,7 @@ public: result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx, eExecutionPolicyAlways, lldb::eLanguageTypeUnknown, + ClangUserExpression::eResultTypeAny, discard_on_error, bp_loc_sp->GetConditionText(), NULL, @@ -494,6 +495,7 @@ public: result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx, eExecutionPolicyAlways, lldb::eLanguageTypeUnknown, + ClangUserExpression::eResultTypeAny, discard_on_error, wp_sp->GetConditionText(), NULL, diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 902ffc77ac7..c31b0b1d9d4 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -1462,6 +1462,7 @@ Target::EvaluateExpression 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 @@ Target::EvaluateExpression execution_results = ClangUserExpression::Evaluate (exe_ctx, execution_policy, lldb::eLanguageTypeUnknown, + coerce_to_id ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny, unwind_on_error, expr_cstr, prefix, diff --git a/lldb/test/lang/objc/foundation/TestObjCMethods2.py b/lldb/test/lang/objc/foundation/TestObjCMethods2.py index 83d772b773f..6b10afc5e24 100644 --- a/lldb/test/lang/objc/foundation/TestObjCMethods2.py +++ b/lldb/test/lang/objc/foundation/TestObjCMethods2.py @@ -61,6 +61,16 @@ class FoundationTestCase2(TestBase): """Test that po of the result of an unknown method doesn't require a cast.""" self.buildDsym() self.NSError_po() + + def test_NSError_p_with_dsym(self): + """Test that p of the result of an unknown method does require a cast.""" + self.buildDsym() + self.NSError_p() + + def test_NSError_p_with_dwarf(self): + """Test that p of the result of an unknown method does require a cast.""" + self.buildDsym() + self.NSError_p() def setUp(self): # Call super's setUp(). @@ -204,6 +214,24 @@ class FoundationTestCase2(TestBase): patterns = ["\(id\) \$.* = ", "Error Domain=Hello", "Code=35", "be completed."]) self.runCmd("process continue") + def NSError_p(self): + """Test that p of the result of an unknown method does require a cast.""" + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + line = self.lines[4] + + self.expect("breakpoint set -f main.m -l %d" % line, BREAKPOINT_CREATED, + substrs = ["Breakpoint created:", + "file ='main.m', line = %d, locations = 1" % line]) + + self.runCmd("run", RUN_SUCCEEDED) + + self.expect("p [NSError errorWithDomain:@\"Hello\" code:35 userInfo:nil]", + error = True, + patterns = ["no known method", "cast the message send to the method's return type"]) + self.runCmd("process continue") + if __name__ == '__main__': import atexit lldb.SBDebugger.Initialize() |