/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- ClangUserExpression.h -----------------------------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGUSEREXPRESSION_H |
10 | | #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGUSEREXPRESSION_H |
11 | | |
12 | | #include <optional> |
13 | | #include <vector> |
14 | | |
15 | | #include "ASTResultSynthesizer.h" |
16 | | #include "ASTStructExtractor.h" |
17 | | #include "ClangExpressionDeclMap.h" |
18 | | #include "ClangExpressionHelper.h" |
19 | | #include "ClangExpressionSourceCode.h" |
20 | | #include "ClangExpressionVariable.h" |
21 | | #include "IRForTarget.h" |
22 | | |
23 | | #include "lldb/Core/Address.h" |
24 | | #include "lldb/Expression/LLVMUserExpression.h" |
25 | | #include "lldb/Expression/Materializer.h" |
26 | | #include "lldb/Target/ExecutionContext.h" |
27 | | #include "lldb/lldb-forward.h" |
28 | | #include "lldb/lldb-private.h" |
29 | | |
30 | | namespace lldb_private { |
31 | | |
32 | | class ClangExpressionParser; |
33 | | |
34 | | /// \class ClangUserExpression ClangUserExpression.h |
35 | | /// "lldb/Expression/ClangUserExpression.h" Encapsulates a single expression |
36 | | /// for use with Clang |
37 | | /// |
38 | | /// LLDB uses expressions for various purposes, notably to call functions |
39 | | /// and as a backend for the expr command. ClangUserExpression encapsulates |
40 | | /// the objects needed to parse and interpret or JIT an expression. It uses |
41 | | /// the Clang parser to produce LLVM IR from the expression. |
42 | | class ClangUserExpression : public LLVMUserExpression { |
43 | | // LLVM RTTI support |
44 | | static char ID; |
45 | | |
46 | | public: |
47 | 7.33k | bool isA(const void *ClassID) const override { |
48 | 7.33k | return ClassID == &ID || LLVMUserExpression::isA(ClassID)0 ; |
49 | 7.33k | } |
50 | 12.0k | static bool classof(const Expression *obj) { return obj->isA(&ID); } |
51 | | |
52 | | enum { kDefaultTimeout = 500000u }; |
53 | | |
54 | | class ClangUserExpressionHelper |
55 | | : public llvm::RTTIExtends<ClangUserExpressionHelper, |
56 | | ClangExpressionHelper> { |
57 | | public: |
58 | | // LLVM RTTI support |
59 | | static char ID; |
60 | | |
61 | | ClangUserExpressionHelper(Target &target, bool top_level) |
62 | 7.27k | : m_target(target), m_top_level(top_level) {} |
63 | | |
64 | | /// Return the object that the parser should use when resolving external |
65 | | /// values. May be NULL if everything should be self-contained. |
66 | 21.5k | ClangExpressionDeclMap *DeclMap() override { |
67 | 21.5k | return m_expr_decl_map_up.get(); |
68 | 21.5k | } |
69 | | |
70 | 7.27k | void ResetDeclMap() { m_expr_decl_map_up.reset(); } |
71 | | |
72 | | void ResetDeclMap(ExecutionContext &exe_ctx, |
73 | | Materializer::PersistentVariableDelegate &result_delegate, |
74 | | bool keep_result_in_memory, |
75 | | ValueObject *ctx_obj); |
76 | | |
77 | | /// Return the object that the parser should allow to access ASTs. May be |
78 | | /// NULL if the ASTs do not need to be transformed. |
79 | | /// |
80 | | /// \param[in] passthrough |
81 | | /// The ASTConsumer that the returned transformer should send |
82 | | /// the ASTs to after transformation. |
83 | | clang::ASTConsumer * |
84 | | ASTTransformer(clang::ASTConsumer *passthrough) override; |
85 | | |
86 | | void CommitPersistentDecls() override; |
87 | | |
88 | | private: |
89 | | Target &m_target; |
90 | | std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up; |
91 | | std::unique_ptr<ASTStructExtractor> m_struct_extractor_up; ///< The class |
92 | | ///that generates |
93 | | ///the argument |
94 | | ///struct layout. |
95 | | std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer_up; |
96 | | bool m_top_level; |
97 | | }; |
98 | | |
99 | | /// Constructor |
100 | | /// |
101 | | /// \param[in] expr |
102 | | /// The expression to parse. |
103 | | /// |
104 | | /// \param[in] prefix |
105 | | /// If non-NULL, a C string containing translation-unit level |
106 | | /// definitions to be included when the expression is parsed. |
107 | | /// |
108 | | /// \param[in] language |
109 | | /// If not eLanguageTypeUnknown, a language to use when parsing |
110 | | /// the expression. Currently restricted to those languages |
111 | | /// supported by Clang. |
112 | | /// |
113 | | /// \param[in] desired_type |
114 | | /// If not eResultTypeAny, the type to use for the expression |
115 | | /// result. |
116 | | /// |
117 | | /// \param[in] options |
118 | | /// Additional options for the expression. |
119 | | /// |
120 | | /// \param[in] ctx_obj |
121 | | /// The object (if any) in which context the expression |
122 | | /// must be evaluated. For details see the comment to |
123 | | /// `UserExpression::Evaluate`. |
124 | | ClangUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr, |
125 | | llvm::StringRef prefix, lldb::LanguageType language, |
126 | | ResultType desired_type, |
127 | | const EvaluateExpressionOptions &options, |
128 | | ValueObject *ctx_obj); |
129 | | |
130 | | ~ClangUserExpression() override; |
131 | | |
132 | | /// Parse the expression |
133 | | /// |
134 | | /// \param[in] diagnostic_manager |
135 | | /// A diagnostic manager to report parse errors and warnings to. |
136 | | /// |
137 | | /// \param[in] exe_ctx |
138 | | /// The execution context to use when looking up entities that |
139 | | /// are needed for parsing (locations of functions, types of |
140 | | /// variables, persistent variables, etc.) |
141 | | /// |
142 | | /// \param[in] execution_policy |
143 | | /// Determines whether interpretation is possible or mandatory. |
144 | | /// |
145 | | /// \param[in] keep_result_in_memory |
146 | | /// True if the resulting persistent variable should reside in |
147 | | /// target memory, if applicable. |
148 | | /// |
149 | | /// \return |
150 | | /// True on success (no errors); false otherwise. |
151 | | bool Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, |
152 | | lldb_private::ExecutionPolicy execution_policy, |
153 | | bool keep_result_in_memory, bool generate_debug_info) override; |
154 | | |
155 | | bool Complete(ExecutionContext &exe_ctx, CompletionRequest &request, |
156 | | unsigned complete_pos) override; |
157 | | |
158 | 14.2k | ExpressionTypeSystemHelper *GetTypeSystemHelper() override { |
159 | 14.2k | return &m_type_system_helper; |
160 | 14.2k | } |
161 | | |
162 | 7.34k | ClangExpressionDeclMap *DeclMap() { return m_type_system_helper.DeclMap(); } |
163 | | |
164 | 7.27k | void ResetDeclMap() { m_type_system_helper.ResetDeclMap(); } |
165 | | |
166 | | void ResetDeclMap(ExecutionContext &exe_ctx, |
167 | | Materializer::PersistentVariableDelegate &result_delegate, |
168 | 7.27k | bool keep_result_in_memory) { |
169 | 7.27k | m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, |
170 | 7.27k | keep_result_in_memory, |
171 | 7.27k | m_ctx_obj); |
172 | 7.27k | } |
173 | | |
174 | | lldb::ExpressionVariableSP |
175 | | GetResultAfterDematerialization(ExecutionContextScope *exe_scope) override; |
176 | | |
177 | | /// Returns true iff this expression is using any imported C++ modules. |
178 | 7.27k | bool DidImportCxxModules() const { return !m_imported_cpp_modules.empty(); } |
179 | | |
180 | | private: |
181 | | /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the |
182 | | /// environment. |
183 | | |
184 | | /// Contains the actual parsing implementation. |
185 | | /// The parameter have the same meaning as in ClangUserExpression::Parse. |
186 | | /// \see ClangUserExpression::Parse |
187 | | bool TryParse(DiagnosticManager &diagnostic_manager, |
188 | | ExecutionContextScope *exe_scope, ExecutionContext &exe_ctx, |
189 | | lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, |
190 | | bool generate_debug_info); |
191 | | |
192 | | void SetupCppModuleImports(ExecutionContext &exe_ctx); |
193 | | |
194 | | void ScanContext(ExecutionContext &exe_ctx, |
195 | | lldb_private::Status &err) override; |
196 | | |
197 | | bool AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, |
198 | | lldb::addr_t struct_address, |
199 | | DiagnosticManager &diagnostic_manager) override; |
200 | | |
201 | | void CreateSourceCode(DiagnosticManager &diagnostic_manager, |
202 | | ExecutionContext &exe_ctx, |
203 | | std::vector<std::string> modules_to_import, |
204 | | bool for_completion); |
205 | | |
206 | | lldb::addr_t GetCppObjectPointer(lldb::StackFrameSP frame, |
207 | | llvm::StringRef object_name, Status &err); |
208 | | |
209 | | /// Defines how the current expression should be wrapped. |
210 | | ClangExpressionSourceCode::WrapKind GetWrapKind() const; |
211 | | bool SetupPersistentState(DiagnosticManager &diagnostic_manager, |
212 | | ExecutionContext &exe_ctx); |
213 | | bool PrepareForParsing(DiagnosticManager &diagnostic_manager, |
214 | | ExecutionContext &exe_ctx, bool for_completion); |
215 | | |
216 | | ClangUserExpressionHelper m_type_system_helper; |
217 | | |
218 | | class ResultDelegate : public Materializer::PersistentVariableDelegate { |
219 | | public: |
220 | 7.27k | ResultDelegate(lldb::TargetSP target) : m_target_sp(target) {} |
221 | | ConstString GetName() override; |
222 | | void DidDematerialize(lldb::ExpressionVariableSP &variable) override; |
223 | | |
224 | | void RegisterPersistentState(PersistentExpressionState *persistent_state); |
225 | | lldb::ExpressionVariableSP &GetVariable(); |
226 | | |
227 | | private: |
228 | | PersistentExpressionState *m_persistent_state; |
229 | | lldb::ExpressionVariableSP m_variable; |
230 | | lldb::TargetSP m_target_sp; |
231 | | }; |
232 | | |
233 | | /// The include directories that should be used when parsing the expression. |
234 | | std::vector<std::string> m_include_directories; |
235 | | |
236 | | /// The absolute character position in the transformed source code where the |
237 | | /// user code (as typed by the user) starts. If the variable is empty, then we |
238 | | /// were not able to calculate this position. |
239 | | std::optional<size_t> m_user_expression_start_pos; |
240 | | ResultDelegate m_result_delegate; |
241 | | ClangPersistentVariables *m_clang_state; |
242 | | std::unique_ptr<ClangExpressionSourceCode> m_source_code; |
243 | | /// The parser instance we used to parse the expression. |
244 | | std::unique_ptr<ClangExpressionParser> m_parser; |
245 | | /// File name used for the expression. |
246 | | std::string m_filename; |
247 | | |
248 | | /// The object (if any) in which context the expression is evaluated. |
249 | | /// See the comment to `UserExpression::Evaluate` for details. |
250 | | ValueObject *m_ctx_obj; |
251 | | |
252 | | /// A list of module names that should be imported when parsing. |
253 | | /// \see CppModuleConfiguration::GetImportedModules |
254 | | std::vector<std::string> m_imported_cpp_modules; |
255 | | |
256 | | /// True if the expression parser should enforce the presence of a valid class |
257 | | /// pointer in order to generate the expression as a method. |
258 | | bool m_enforce_valid_object = true; |
259 | | /// True if the expression is compiled as a C++ member function (true if it |
260 | | /// was parsed when exe_ctx was in a C++ method). |
261 | | bool m_in_cplusplus_method = false; |
262 | | /// True if the expression is compiled as an Objective-C method (true if it |
263 | | /// was parsed when exe_ctx was in an Objective-C method). |
264 | | bool m_in_objectivec_method = false; |
265 | | /// True if the expression is compiled as a static (or class) method |
266 | | /// (currently true if it was parsed when exe_ctx was in an Objective-C class |
267 | | /// method). |
268 | | bool m_in_static_method = false; |
269 | | /// True if "this" or "self" must be looked up and passed in. False if the |
270 | | /// expression doesn't really use them and they can be NULL. |
271 | | bool m_needs_object_ptr = false; |
272 | | }; |
273 | | |
274 | | } // namespace lldb_private |
275 | | |
276 | | #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGUSEREXPRESSION_H |