diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h @@ -28,20 +28,30 @@ static const llvm::StringRef g_prefix_file_name; static const char *g_expression_prefix; + /// The possible ways an expression can be wrapped. + enum class WrapKind { + /// Wrapped in a non-static member function of a C++ class. + CppMemberFunction, + /// Wrapped in an instance Objective-C method. + ObjCInstanceMethod, + /// Wrapped in a static Objective-C method. + ObjCStaticMethod, + /// Wrapped in a non-member function. + /// Note that this is also used for static member functions of a C++ class. + Function + }; + static ClangExpressionSourceCode *CreateWrapped(llvm::StringRef filename, llvm::StringRef prefix, - llvm::StringRef body) { + llvm::StringRef body, + WrapKind wrap_kind) { return new ClangExpressionSourceCode(filename, "$__lldb_expr", prefix, body, - Wrap); + Wrap, wrap_kind); } /// Generates the source code that will evaluate the expression. /// /// \param text output parameter containing the source code string. - /// \param wrapping_language If the expression is supossed to be wrapped, - /// then this is the language that should be used for that. - /// \param static_method True iff the expression is valuated inside a static - /// Objective-C method. /// \param exe_ctx The execution context in which the expression will be /// evaluated. /// \param add_locals True iff local variables should be injected into the @@ -51,8 +61,7 @@ /// \param modules A list of (C++) modules that the expression should import. /// /// \return true iff the source code was successfully generated. - bool GetText(std::string &text, lldb::LanguageType wrapping_language, - bool static_method, ExecutionContext &exe_ctx, bool add_locals, + bool GetText(std::string &text, ExecutionContext &exe_ctx, bool add_locals, bool force_add_all_locals, llvm::ArrayRef modules) const; @@ -60,19 +69,24 @@ // passed to CreateWrapped. Return true if the bounds could be found. This // will also work on text with FixItHints applied. bool GetOriginalBodyBounds(std::string transformed_text, - lldb::LanguageType wrapping_language, size_t &start_loc, size_t &end_loc); protected: ClangExpressionSourceCode(llvm::StringRef filename, llvm::StringRef name, llvm::StringRef prefix, llvm::StringRef body, - Wrapping wrap); + Wrapping wrap, WrapKind wrap_kind); private: + void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, + StreamString &stream, + const std::string &expr) const; + /// String marking the start of the user expression. std::string m_start_marker; /// String marking the end of the user expression. std::string m_end_marker; + /// How the expression has been wrapped. + const WrapKind m_wrap_kind; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -174,8 +174,8 @@ lldb_private::ClangExpressionSourceCode::ClangExpressionSourceCode( llvm::StringRef filename, llvm::StringRef name, llvm::StringRef prefix, - llvm::StringRef body, Wrapping wrap) - : ExpressionSourceCode(name, prefix, body, wrap) { + llvm::StringRef body, Wrapping wrap, WrapKind wrap_kind) + : ExpressionSourceCode(name, prefix, body, wrap), m_wrap_kind(wrap_kind) { // Use #line markers to pretend that we have a single-line source file // containing only the user expression. This will hide our wrapper code // from the user when we render diagnostics with Clang. @@ -261,10 +261,9 @@ } } -static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, - StreamString &stream, - const std::string &expr, - lldb::LanguageType wrapping_language) { +void ClangExpressionSourceCode::AddLocalVariableDecls( + const lldb::VariableListSP &var_list_sp, StreamString &stream, + const std::string &expr) const { TokenVerifier tokens(expr); for (size_t i = 0; i < var_list_sp->GetSize(); i++) { @@ -281,13 +280,12 @@ if (!expr.empty() && !tokens.hasToken(var_name.GetStringRef())) continue; - if ((var_name == "self" || var_name == "_cmd") && - (wrapping_language == lldb::eLanguageTypeObjC || - wrapping_language == lldb::eLanguageTypeObjC_plus_plus)) + const bool is_objc = m_wrap_kind == WrapKind::ObjCInstanceMethod || + m_wrap_kind == WrapKind::ObjCStaticMethod; + if ((var_name == "self" || var_name == "_cmd") && is_objc) continue; - if (var_name == "this" && - wrapping_language == lldb::eLanguageTypeC_plus_plus) + if (var_name == "this" && m_wrap_kind == WrapKind::CppMemberFunction) continue; stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString()); @@ -295,9 +293,8 @@ } bool ClangExpressionSourceCode::GetText( - std::string &text, lldb::LanguageType wrapping_language, bool static_method, - ExecutionContext &exe_ctx, bool add_locals, bool force_add_all_locals, - llvm::ArrayRef modules) const { + std::string &text, ExecutionContext &exe_ctx, bool add_locals, + bool force_add_all_locals, llvm::ArrayRef modules) const { const char *target_specific_defines = "typedef signed char BOOL;\n"; std::string module_macros; @@ -374,21 +371,11 @@ lldb::VariableListSP var_list_sp = frame->GetInScopeVariableList(false, true); AddLocalVariableDecls(var_list_sp, lldb_local_var_decls, - force_add_all_locals ? "" : m_body, - wrapping_language); + force_add_all_locals ? "" : m_body); } } if (m_wrap) { - switch (wrapping_language) { - default: - return false; - case lldb::eLanguageTypeC: - case lldb::eLanguageTypeC_plus_plus: - case lldb::eLanguageTypeObjC: - break; - } - // Generate a list of @import statements that will import the specified // module into our expression. std::string module_imports; @@ -407,22 +394,12 @@ // 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(m_start_marker); - tagged_body.append(m_body); - tagged_body.append(m_end_marker); - break; - } - switch (wrapping_language) { - default: - break; - case lldb::eLanguageTypeC: + tagged_body.append(m_start_marker); + tagged_body.append(m_body); + tagged_body.append(m_end_marker); + + switch (m_wrap_kind) { + case WrapKind::Function: wrap_stream.Printf("%s" "void \n" "%s(void *$__lldb_arg) \n" @@ -433,7 +410,7 @@ module_imports.c_str(), m_name.c_str(), lldb_local_var_decls.GetData(), tagged_body.c_str()); break; - case lldb::eLanguageTypeC_plus_plus: + case WrapKind::CppMemberFunction: wrap_stream.Printf("%s" "void \n" "$__lldb_class::%s(void *$__lldb_arg) \n" @@ -444,38 +421,38 @@ module_imports.c_str(), m_name.c_str(), lldb_local_var_decls.GetData(), tagged_body.c_str()); break; - case lldb::eLanguageTypeObjC: - if (static_method) { - wrap_stream.Printf( - "%s" - "@interface $__lldb_objc_class ($__lldb_category) \n" - "+(void)%s:(void *)$__lldb_arg; \n" - "@end \n" - "@implementation $__lldb_objc_class ($__lldb_category) \n" - "+(void)%s:(void *)$__lldb_arg \n" - "{ \n" - " %s; \n" - "%s" - "} \n" - "@end \n", - module_imports.c_str(), m_name.c_str(), m_name.c_str(), - lldb_local_var_decls.GetData(), tagged_body.c_str()); - } else { - wrap_stream.Printf( - "%s" - "@interface $__lldb_objc_class ($__lldb_category) \n" - "-(void)%s:(void *)$__lldb_arg; \n" - "@end \n" - "@implementation $__lldb_objc_class ($__lldb_category) \n" - "-(void)%s:(void *)$__lldb_arg \n" - "{ \n" - " %s; \n" - "%s" - "} \n" - "@end \n", - module_imports.c_str(), m_name.c_str(), m_name.c_str(), - lldb_local_var_decls.GetData(), tagged_body.c_str()); - } + case WrapKind::ObjCInstanceMethod: + wrap_stream.Printf( + "%s" + "@interface $__lldb_objc_class ($__lldb_category) \n" + "-(void)%s:(void *)$__lldb_arg; \n" + "@end \n" + "@implementation $__lldb_objc_class ($__lldb_category) \n" + "-(void)%s:(void *)$__lldb_arg \n" + "{ \n" + " %s; \n" + "%s" + "} \n" + "@end \n", + module_imports.c_str(), m_name.c_str(), m_name.c_str(), + lldb_local_var_decls.GetData(), tagged_body.c_str()); + break; + + case WrapKind::ObjCStaticMethod: + wrap_stream.Printf( + "%s" + "@interface $__lldb_objc_class ($__lldb_category) \n" + "+(void)%s:(void *)$__lldb_arg; \n" + "@end \n" + "@implementation $__lldb_objc_class ($__lldb_category) \n" + "+(void)%s:(void *)$__lldb_arg \n" + "{ \n" + " %s; \n" + "%s" + "} \n" + "@end \n", + module_imports.c_str(), m_name.c_str(), m_name.c_str(), + lldb_local_var_decls.GetData(), tagged_body.c_str()); break; } @@ -488,17 +465,7 @@ } bool ClangExpressionSourceCode::GetOriginalBodyBounds( - std::string transformed_text, lldb::LanguageType wrapping_language, - size_t &start_loc, size_t &end_loc) { - switch (wrapping_language) { - default: - return false; - case lldb::eLanguageTypeC: - case lldb::eLanguageTypeC_plus_plus: - case lldb::eLanguageTypeObjC: - break; - } - + std::string transformed_text, size_t &start_loc, size_t &end_loc) { start_loc = transformed_text.find(m_start_marker); if (start_loc == std::string::npos) return false; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -185,7 +185,8 @@ ExecutionContext &exe_ctx, std::vector modules_to_import, bool for_completion); - void UpdateLanguageForExpr(); + /// Defines how the current expression should be wrapped. + ClangExpressionSourceCode::WrapKind GetWrapKind() const; bool SetupPersistentState(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx); bool PrepareForParsing(DiagnosticManager &diagnostic_manager, @@ -208,8 +209,6 @@ lldb::TargetSP m_target_sp; }; - /// The language type of the current expression. - lldb::LanguageType m_expr_lang = lldb::eLanguageTypeUnknown; /// The include directories that should be used when parsing the expression. std::vector m_include_directories; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -397,16 +397,20 @@ "current compilation unit."); } -void ClangUserExpression::UpdateLanguageForExpr() { - m_expr_lang = lldb::LanguageType::eLanguageTypeUnknown; - if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) - return; +ClangExpressionSourceCode::WrapKind ClangUserExpression::GetWrapKind() const { + assert(m_options.GetExecutionPolicy() != eExecutionPolicyTopLevel && + "Top level expressions aren't wrapped."); + using Kind = ClangExpressionSourceCode::WrapKind; if (m_in_cplusplus_method) - m_expr_lang = lldb::eLanguageTypeC_plus_plus; - else if (m_in_objectivec_method) - m_expr_lang = lldb::eLanguageTypeObjC; - else - m_expr_lang = lldb::eLanguageTypeC; + return Kind::CppMemberFunction; + else if (m_in_objectivec_method) { + if (m_in_static_method) + return Kind::ObjCStaticMethod; + return Kind::ObjCInstanceMethod; + } + // Not in any kind of 'special' function, so just wrap it in a normal C + // function. + return Kind::Function; } void ClangUserExpression::CreateSourceCode( @@ -420,10 +424,9 @@ m_transformed_text = m_expr_text; } else { m_source_code.reset(ClangExpressionSourceCode::CreateWrapped( - m_filename, prefix, m_expr_text)); + m_filename, prefix, m_expr_text, GetWrapKind())); - if (!m_source_code->GetText(m_transformed_text, m_expr_lang, - m_in_static_method, exe_ctx, !m_ctx_obj, + if (!m_source_code->GetText(m_transformed_text, exe_ctx, !m_ctx_obj, for_completion, modules_to_import)) { diagnostic_manager.PutString(eDiagnosticSeverityError, "couldn't construct expression body"); @@ -435,7 +438,7 @@ std::size_t original_start; std::size_t original_end; bool found_bounds = m_source_code->GetOriginalBodyBounds( - m_transformed_text, m_expr_lang, original_start, original_end); + m_transformed_text, original_start, original_end); if (found_bounds) m_user_expression_start_pos = original_start; } @@ -560,7 +563,6 @@ llvm::make_range(m_include_directories.begin(), m_include_directories.end())); - UpdateLanguageForExpr(); CreateSourceCode(diagnostic_manager, exe_ctx, imported_modules, for_completion); return true; @@ -635,9 +637,8 @@ m_fixed_text = diagnostic_manager.GetFixedExpression(); // Retrieve the original expression in case we don't have a top level // expression (which has no surrounding source code). - if (m_source_code && - m_source_code->GetOriginalBodyBounds(m_fixed_text, m_expr_lang, - fixed_start, fixed_end)) + if (m_source_code && m_source_code->GetOriginalBodyBounds( + m_fixed_text, fixed_start, fixed_end)) m_fixed_text = m_fixed_text.substr(fixed_start, fixed_end - fixed_start); }