================ @@ -232,4 +263,105 @@ Interpreter::Visit(const IdentifierNode *node) { return identifier; } -} // namespace lldb_private::dil +llvm::Expected<lldb::ValueObjectSP> +Interpreter::Visit(const UnaryOpNode *node) { + FlowAnalysis rhs_flow( + /* address_of_is_pending */ node->kind() == UnaryOpKind::AddrOf); + + Status error; + auto rhs_or_err = EvaluateNode(node->rhs(), &rhs_flow); + if (!rhs_or_err) { + return rhs_or_err; + } + lldb::ValueObjectSP rhs = *rhs_or_err; + + CompilerType rhs_type = rhs->GetCompilerType(); + switch (node->kind()) { + case UnaryOpKind::Deref: { + if (rhs_type.IsArrayType()) + rhs = ArrayToPointerConversion(rhs, m_exe_ctx_scope); + + lldb::ValueObjectSP dynamic_rhs = rhs->GetDynamicValue(m_default_dynamic); + if (dynamic_rhs) + rhs = dynamic_rhs; + + if (rhs->GetCompilerType().IsPointerType()) { + if (rhs->GetCompilerType().IsPointerToVoid()) { + return llvm::make_error<DILDiagnosticError>( + m_expr, "indirection not permitted on operand of type 'void *'", + node->GetLocation(), 1); + } + return EvaluateDereference(rhs); + } + lldb::ValueObjectSP child_sp = rhs->Dereference(error); + if (error.Success()) + rhs = child_sp; + + return rhs; + } + case UnaryOpKind::AddrOf: { + if (node->rhs()->is_rvalue()) { + std::string errMsg = + llvm::formatv("cannot take the address of an rvalue of type {0}", + rhs_type.TypeDescription()); + return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, + node->GetLocation()); + } + if (rhs->IsBitfield()) { + return llvm::make_error<DILDiagnosticError>( + m_expr, "address of bit-field requested", node->GetLocation()); + } + // If the address-of operation wasn't cancelled during the evaluation of + // RHS (e.g. because of the address-of-a-dereference elision), apply it + // here. + if (rhs_flow.AddressOfIsPending()) { + Status error; + lldb::ValueObjectSP value = rhs->AddressOf(error); + if (error.Fail()) { + return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(), + node->GetLocation()); + } + return value; + } + return rhs; + } + } + + // Unsupported/invalid operation. + return llvm::make_error<DILDiagnosticError>( + m_expr, "invalid ast: unexpected binary operator", node->GetLocation(), + 1); +} + +lldb::ValueObjectSP Interpreter::EvaluateDereference(lldb::ValueObjectSP rhs) { + // If rhs is a reference, dereference it first. + Status error; + if (rhs->GetCompilerType().IsReferenceType()) + rhs = rhs->Dereference(error); + + assert(rhs->GetCompilerType().IsPointerType() && + "invalid ast: must be a pointer type"); + + if (rhs->GetDerefValobj()) ---------------- kuilpd wrote:
This checks if the value has already been dereferenced. The same check is also done in the beginning of `Dereference()`, but if we want to skip `CreateValueObjectFromAddress` as well, this is done separately beforehand. https://github.com/llvm/llvm-project/pull/134428 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits