1818
1919namespace lldb_private ::dil {
2020
21+ static lldb::ValueObjectSP
22+ ArrayToPointerConversion (lldb::ValueObjectSP valobj,
23+ std::shared_ptr<ExecutionContextScope> ctx) {
24+ assert (valobj->IsArrayType () &&
25+ " an argument to array-to-pointer conversion must be an array" );
26+
27+ uint64_t addr = valobj->GetLoadAddress ();
28+ llvm::StringRef name = " result" ;
29+ ExecutionContext exe_ctx;
30+ ctx->CalculateExecutionContext (exe_ctx);
31+ return ValueObject::CreateValueObjectFromAddress (
32+ name, addr, exe_ctx,
33+ valobj->GetCompilerType ().GetArrayElementType (ctx.get ()).GetPointerType (),
34+ /* do_deref */ false );
35+ }
36+
2137static lldb::ValueObjectSP LookupStaticIdentifier (
2238 VariableList &variable_list, std::shared_ptr<StackFrame> exe_scope,
2339 llvm::StringRef name_ref, llvm::StringRef unqualified_name) {
@@ -206,10 +222,25 @@ Interpreter::Interpreter(lldb::TargetSP target, llvm::StringRef expr,
206222 : m_target(std::move(target)), m_expr(expr), m_default_dynamic(use_dynamic),
207223 m_exe_ctx_scope (frame_sp) {}
208224
209- llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate (const ASTNode *node) {
225+ llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate (const ASTNode *tree) {
226+ // Evaluate an AST.
227+ auto value_or_error = EvaluateNode (tree);
228+
229+ // Return the computed result-or-error.
230+ return value_or_error;
231+ }
210232
233+ llvm::Expected<lldb::ValueObjectSP>
234+ Interpreter::EvaluateNode (const ASTNode *node, FlowAnalysis *flow) {
235+ // Set up the evaluation context for the current node.
236+ m_flow_analysis_chain.push_back (flow);
211237 // Traverse an AST pointed by the `node`.
212- return node->Accept (this );
238+ auto value_or_error = node->Accept (this );
239+ // Cleanup the context.
240+ m_flow_analysis_chain.pop_back ();
241+ // Return the computed value-or-error. The caller is responsible for
242+ // checking if an error occured during the evaluation.
243+ return value_or_error;
213244}
214245
215246llvm::Expected<lldb::ValueObjectSP>
@@ -232,4 +263,106 @@ Interpreter::Visit(const IdentifierNode *node) {
232263 return identifier;
233264}
234265
235- } // namespace lldb_private::dil
266+ llvm::Expected<lldb::ValueObjectSP>
267+ Interpreter::Visit (const UnaryOpNode *node) {
268+ FlowAnalysis rhs_flow (
269+ /* address_of_is_pending */ node->kind () == UnaryOpKind::AddrOf);
270+
271+ Status error;
272+ auto rhs_or_err = EvaluateNode (node->rhs (), &rhs_flow);
273+ if (!rhs_or_err) {
274+ return rhs_or_err;
275+ }
276+ lldb::ValueObjectSP rhs = *rhs_or_err;
277+
278+ if (rhs->GetCompilerType ().IsReferenceType ()) {
279+ rhs = rhs->Dereference (error);
280+ if (error.Fail ()) {
281+ return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString (),
282+ node->GetLocation ());
283+ }
284+ }
285+ CompilerType rhs_type = rhs->GetCompilerType ();
286+ switch (node->kind ()) {
287+ case UnaryOpKind::Deref: {
288+ if (rhs_type.IsArrayType ())
289+ rhs = ArrayToPointerConversion (rhs, m_exe_ctx_scope);
290+
291+ lldb::ValueObjectSP dynamic_rhs = rhs->GetDynamicValue (m_default_dynamic);
292+ if (dynamic_rhs)
293+ rhs = dynamic_rhs;
294+
295+ if (rhs->GetCompilerType ().IsPointerType ())
296+ return EvaluateDereference (rhs);
297+ lldb::ValueObjectSP child_sp = rhs->Dereference (error);
298+ if (error.Success ())
299+ rhs = child_sp;
300+
301+ return rhs;
302+ }
303+ case UnaryOpKind::AddrOf: {
304+ if (node->rhs ()->is_rvalue ()) {
305+ std::string errMsg =
306+ llvm::formatv (" cannot take the address of an rvalue of type {0}" ,
307+ rhs_type.TypeDescription ());
308+ return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
309+ node->GetLocation ());
310+ }
311+ if (rhs->IsBitfield ()) {
312+ return llvm::make_error<DILDiagnosticError>(
313+ m_expr, " address of bit-field requested" , node->GetLocation ());
314+ }
315+ // If the address-of operation wasn't cancelled during the evaluation of
316+ // RHS (e.g. because of the address-of-a-dereference elision), apply it
317+ // here.
318+ if (rhs_flow.AddressOfIsPending ()) {
319+ Status error;
320+ lldb::ValueObjectSP value = rhs->AddressOf (error);
321+ if (error.Fail ()) {
322+ return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString (),
323+ node->GetLocation ());
324+ }
325+ return value;
326+ }
327+ return rhs;
328+ }
329+ }
330+
331+ // Unsupported/invalid operation.
332+ return llvm::make_error<DILDiagnosticError>(
333+ m_expr, " invalid ast: unexpected binary operator" , node->GetLocation (),
334+ 1 );
335+ }
336+
337+ lldb::ValueObjectSP Interpreter::EvaluateDereference (lldb::ValueObjectSP rhs) {
338+ // If rhs is a reference, dereference it first.
339+ Status error;
340+ if (rhs->GetCompilerType ().IsReferenceType ())
341+ rhs = rhs->Dereference (error);
342+
343+ assert (rhs->GetCompilerType ().IsPointerType () &&
344+ " invalid ast: must be a pointer type" );
345+
346+ if (rhs->GetDerefValobj ())
347+ return rhs->GetDerefValobj ()->GetSP ();
348+
349+ CompilerType pointer_type = rhs->GetCompilerType ();
350+ lldb::addr_t base_addr = rhs->GetValueAsUnsigned (0 );
351+
352+ llvm::StringRef name = " result" ;
353+ ExecutionContext exe_ctx (m_target.get (), false );
354+ lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromAddress (
355+ name, base_addr, exe_ctx, pointer_type,
356+ /* do_deref */ false );
357+
358+ // If we're in the address-of context, skip the dereference and cancel the
359+ // pending address-of operation as well.
360+ if (flow_analysis () && flow_analysis ()->AddressOfIsPending ()) {
361+ flow_analysis ()->DiscardAddressOf ();
362+ return value;
363+ }
364+
365+ return value->Dereference (error);
366+ }
367+
368+ } // namespace lldb_private::dil
0 commit comments