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.
}
}
-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++) {
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());
}
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<std::string> modules) const {
+ std::string &text, ExecutionContext &exe_ctx, bool add_locals,
+ bool force_add_all_locals, llvm::ArrayRef<std::string> modules) const {
const char *target_specific_defines = "typedef signed char BOOL;\n";
std::string module_macros;
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;
// 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"
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"
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;
}
}
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;
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
/// \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<std::string> modules) const;
// 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
"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(
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");
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;
}
llvm::make_range(m_include_directories.begin(),
m_include_directories.end()));
- UpdateLanguageForExpr();
CreateSourceCode(diagnostic_manager, exe_ctx, imported_modules,
for_completion);
return true;
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);
}