@@ -201,10 +201,13 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
201201}
202202
203203Interpreter::Interpreter (lldb::TargetSP target, llvm::StringRef expr,
204- lldb::DynamicValueType use_dynamic,
205- std::shared_ptr<StackFrame> frame_sp)
206- : m_target(std::move(target)), m_expr(expr), m_default_dynamic(use_dynamic),
207- m_exe_ctx_scope (frame_sp) {}
204+ std::shared_ptr<StackFrame> frame_sp,
205+ lldb::DynamicValueType use_dynamic, bool use_synthetic,
206+ bool fragile_ivar, bool check_ptr_vs_member)
207+ : m_target(std::move(target)), m_expr(expr), m_exe_ctx_scope(frame_sp),
208+ m_use_dynamic (use_dynamic), m_use_synthetic(use_synthetic),
209+ m_fragile_ivar(fragile_ivar), m_check_ptr_vs_member(check_ptr_vs_member) {
210+ }
208211
209212llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate (const ASTNode *node) {
210213 // Evaluate an AST.
@@ -216,7 +219,7 @@ llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate(const ASTNode *node) {
216219
217220llvm::Expected<lldb::ValueObjectSP>
218221Interpreter::Visit (const IdentifierNode *node) {
219- lldb::DynamicValueType use_dynamic = m_default_dynamic ;
222+ lldb::DynamicValueType use_dynamic = m_use_dynamic ;
220223
221224 lldb::ValueObjectSP identifier =
222225 LookupIdentifier (node->GetName (), m_exe_ctx_scope, use_dynamic);
@@ -245,7 +248,7 @@ Interpreter::Visit(const UnaryOpNode *node) {
245248
246249 switch (node->kind ()) {
247250 case UnaryOpKind::Deref: {
248- lldb::ValueObjectSP dynamic_rhs = rhs->GetDynamicValue (m_default_dynamic );
251+ lldb::ValueObjectSP dynamic_rhs = rhs->GetDynamicValue (m_use_dynamic );
249252 if (dynamic_rhs)
250253 rhs = dynamic_rhs;
251254
@@ -272,4 +275,112 @@ Interpreter::Visit(const UnaryOpNode *node) {
272275 m_expr, " invalid ast: unexpected binary operator" , node->GetLocation ());
273276}
274277
278+ llvm::Expected<lldb::ValueObjectSP>
279+ Interpreter::Visit (const MemberOfNode *node) {
280+ auto base_or_err = Evaluate (node->GetBase ());
281+ if (!base_or_err)
282+ return base_or_err;
283+ lldb::ValueObjectSP base = *base_or_err;
284+
285+ // Perform some basic type & correctness checking.
286+ if (node->GetIsArrow ()) {
287+ if (!m_fragile_ivar) {
288+ // Make sure we aren't trying to deref an objective
289+ // C ivar if this is not allowed
290+ const uint32_t pointer_type_flags =
291+ base->GetCompilerType ().GetTypeInfo (nullptr );
292+ if ((pointer_type_flags & lldb::eTypeIsObjC) &&
293+ (pointer_type_flags & lldb::eTypeIsPointer)) {
294+ // This was an objective C object pointer and it was requested we
295+ // skip any fragile ivars so return nothing here
296+ return lldb::ValueObjectSP ();
297+ }
298+ }
299+
300+ // If we have a non-pointer type with a synthetic value then lets check
301+ // if we have a synthetic dereference specified.
302+ if (!base->IsPointerType () && base->HasSyntheticValue ()) {
303+ Status deref_error;
304+ if (lldb::ValueObjectSP synth_deref_sp =
305+ base->GetSyntheticValue ()->Dereference (deref_error);
306+ synth_deref_sp && deref_error.Success ()) {
307+ base = std::move (synth_deref_sp);
308+ }
309+ if (!base || deref_error.Fail ()) {
310+ std::string errMsg = llvm::formatv (
311+ " Failed to dereference synthetic value: {0}" , deref_error);
312+ return llvm::make_error<DILDiagnosticError>(
313+ m_expr, errMsg, node->GetLocation (), node->GetFieldName ().size ());
314+ }
315+
316+ // Some synthetic plug-ins fail to set the error in Dereference
317+ if (!base) {
318+ std::string errMsg = " Failed to dereference synthetic value" ;
319+ return llvm::make_error<DILDiagnosticError>(
320+ m_expr, errMsg, node->GetLocation (), node->GetFieldName ().size ());
321+ }
322+ }
323+ }
324+
325+ if (m_check_ptr_vs_member) {
326+ bool expr_is_ptr = node->GetIsArrow ();
327+ bool base_is_ptr = base->IsPointerType ();
328+
329+ if (expr_is_ptr != base_is_ptr) {
330+ if (base_is_ptr) {
331+ std::string errMsg =
332+ llvm::formatv (" member reference type {0} is a pointer; "
333+ " did you mean to use '->'?" ,
334+ base->GetCompilerType ().TypeDescription ());
335+ return llvm::make_error<DILDiagnosticError>(
336+ m_expr, errMsg, node->GetLocation (), node->GetFieldName ().size ());
337+ } else {
338+ std::string errMsg =
339+ llvm::formatv (" member reference type {0} is not a pointer; "
340+ " did you mean to use '.'?" ,
341+ base->GetCompilerType ().TypeDescription ());
342+ return llvm::make_error<DILDiagnosticError>(
343+ m_expr, errMsg, node->GetLocation (), node->GetFieldName ().size ());
344+ }
345+ }
346+ }
347+
348+ lldb::ValueObjectSP field_obj =
349+ base->GetChildMemberWithName (node->GetFieldName ());
350+ if (!field_obj) {
351+ if (m_use_synthetic) {
352+ field_obj = base->GetSyntheticValue ();
353+ if (field_obj)
354+ field_obj = field_obj->GetChildMemberWithName (node->GetFieldName ());
355+ }
356+
357+ if (!m_use_synthetic || !field_obj) {
358+ std::string errMsg = llvm::formatv (
359+ " no member named '{0}' in {1}" , node->GetFieldName (),
360+ base->GetCompilerType ().GetFullyUnqualifiedType ().TypeDescription ());
361+ return llvm::make_error<DILDiagnosticError>(
362+ m_expr, errMsg, node->GetLocation (), node->GetFieldName ().size ());
363+ }
364+ }
365+
366+ if (field_obj && field_obj->GetName () == node->GetFieldName ()) {
367+ if (m_use_dynamic != lldb::eNoDynamicValues) {
368+ lldb::ValueObjectSP dynamic_val_sp =
369+ field_obj->GetDynamicValue (m_use_dynamic);
370+ if (dynamic_val_sp)
371+ field_obj = dynamic_val_sp;
372+ }
373+ return field_obj;
374+ }
375+
376+ CompilerType base_type = base->GetCompilerType ();
377+ if (node->GetIsArrow () && base->IsPointerType ())
378+ base_type = base_type.GetPointeeType ();
379+ std::string errMsg =
380+ llvm::formatv (" no member named '{0}' in {1}" , node->GetFieldName (),
381+ base_type.GetFullyUnqualifiedType ().TypeDescription ());
382+ return llvm::make_error<DILDiagnosticError>(
383+ m_expr, errMsg, node->GetLocation (), node->GetFieldName ().size ());
384+ }
385+
275386} // namespace lldb_private::dil
0 commit comments