Summary: ClangExpressionSourceCode has different ways to wrap the user expression based on which context the expression is executed in. For example, if we're in a C++ member function we put the expression inside a fake member function of a fake class to make the evaluation possible. Similar things are done for Objective-C instance/static methods. There is also a default wrapping where we put the expression in a normal function just to make it possible to execute it. The way we currently define which kind of wrapping the expression needs is based on the `wrapping_language` we keep passing to the ClangExpressionSourceCode instance. We repurposed the language type enum for that variable to distinguish the cases above with the following mapping: * language = C_plus_plus -> member function wrapping * language = ObjC -> instance/static method wrapping (`is_static` distinguished between those two). * language = C -> normal function wrapping * all other cases like C_plus_plus11, Haskell etc. make our class a no-op that does mostly nothing. That mapping is currently not documented and just confusing as the `language` is unrelated to the expression language (and in the ClangUserExpression we even pretend that it *is* the actual language, but luckily never used it for anything). Some of the code in ClangExpressionSourceCode is also obviously thinking that this is the actual language of the expression as it checks for non-existent cases such as `ObjC_plus_plus` which is not part of the mapping. This patch makes a new enum to describe the four cases above (with instance/static Objective-C methods now being their own case). It also make that enum just a member of ClangExpressionSourceCode instead of having to pass the same value to the class repeatedly. This gets also rid of all the switch-case-checks for 'unknown' language such as C_plus_plus11 as this is no longer necessary. Reviewers: labath, JDevlieghere Reviewed By: labath Subscribers: abidh Differential Revision: https://reviews.llvm.org/D80793
95 lines
3.7 KiB
C++
95 lines
3.7 KiB
C++
//===-- ClangExpressionSourceCode.h -----------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONSOURCECODE_H
|
|
#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONSOURCECODE_H
|
|
|
|
#include "lldb/Expression/Expression.h"
|
|
#include "lldb/Expression/ExpressionSourceCode.h"
|
|
#include "lldb/lldb-enumerations.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include <string>
|
|
|
|
namespace lldb_private {
|
|
|
|
class ExecutionContext;
|
|
|
|
class ClangExpressionSourceCode : public ExpressionSourceCode {
|
|
public:
|
|
/// The file name we use for the wrapper code that we inject before
|
|
/// the user expression.
|
|
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,
|
|
WrapKind wrap_kind) {
|
|
return new ClangExpressionSourceCode(filename, "$__lldb_expr", prefix, body,
|
|
Wrap, wrap_kind);
|
|
}
|
|
|
|
/// Generates the source code that will evaluate the expression.
|
|
///
|
|
/// \param text output parameter containing the source code string.
|
|
/// \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
|
|
/// expression source code.
|
|
/// \param force_add_all_locals True iff all local variables should be
|
|
/// injected even if they are not used in the expression.
|
|
/// \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, ExecutionContext &exe_ctx, bool add_locals,
|
|
bool force_add_all_locals,
|
|
llvm::ArrayRef<std::string> modules) const;
|
|
|
|
// Given a string returned by GetText, find the beginning and end of the body
|
|
// 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,
|
|
size_t &start_loc, size_t &end_loc);
|
|
|
|
protected:
|
|
ClangExpressionSourceCode(llvm::StringRef filename, llvm::StringRef name,
|
|
llvm::StringRef prefix, llvm::StringRef body,
|
|
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
|
|
|
|
#endif
|