Index: lldb/include/lldb/Core/ExpressionPath.h =================================================================== --- /dev/null +++ lldb/include/lldb/Core/ExpressionPath.h @@ -0,0 +1,160 @@ +//===-- ExpressionPath.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_CORE_EXPRESSIONPATH_H +#define LLDB_CORE_EXPRESSIONPATH_H + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" +#include "lldb/lldb-types.h" + +namespace lldb_private { + +/// Responsible for evaluating LLDB's expression paths which is the +/// domain-specific language of 'frame var' or SBValue::GetExpressionPath. +class ExpressionPath { + // Right now the parser has no state so there is no need to construct one. + ExpressionPath() = default; + +public: + enum class PathFormat { DereferencePointers = 1, HonorPointers }; + + enum class ScanEndReason { + /// Out of data to parse. + EndOfString = 1, + /// Child element not found. + NoSuchChild, + /// (Synthetic) child element not found. + NoSuchSyntheticChild, + /// [] only allowed for arrays. + EmptyRangeNotAllowed, + /// . used when -> should be used. + DotInsteadOfArrow, + /// -> used when . should be used. + ArrowInsteadOfDot, + /// ObjC ivar expansion not allowed. + FragileIVarNotAllowed, + /// [] not allowed by options. + RangeOperatorNotAllowed, + /// [] not valid on objects other than scalars, pointers or arrays. + RangeOperatorInvalid, + /// [] is good for arrays, but I cannot parse it. + ArrayRangeOperatorMet, + /// [] is good for bitfields, but I cannot parse after it. + BitfieldRangeOperatorMet, + /// Something is malformed in he expression. + UnexpectedSymbol, + /// Impossible to apply & operator. + TakingAddressFailed, + /// Impossible to apply * operator. + DereferencingFailed, + /// [] was expanded into a VOList. + RangeOperatorExpanded, + /// getting the synthetic children failed. + SyntheticValueMissing, + Unknown = 0xFFFF + }; + + enum class EndResultType { + /// Anything but... + Plain = 1, + /// A bitfield. + Bitfield, + /// A range [low-high]. + BoundedRange, + /// A range []. + UnboundedRange, + /// Several items in a VOList. + ValueObjectList, + Invalid = 0xFFFF + }; + + enum class Aftermath { + /// Just return it. + Nothing = 1, + /// Dereference the target. + Dereference, + /// Take target's address. + TakeAddress + }; + + struct GetValueOptions { + enum class SyntheticChildrenTraversal { + None, + ToSynthetic, + FromSynthetic, + Both + }; + + bool m_check_dot_vs_arrow_syntax; + bool m_no_fragile_ivar; + bool m_allow_bitfields_syntax; + SyntheticChildrenTraversal m_synthetic_children_traversal; + + GetValueOptions(bool dot = false, bool no_ivar = false, + bool bitfield = true, + SyntheticChildrenTraversal synth_traverse = + SyntheticChildrenTraversal::ToSynthetic) + : m_check_dot_vs_arrow_syntax(dot), m_no_fragile_ivar(no_ivar), + m_allow_bitfields_syntax(bitfield), + m_synthetic_children_traversal(synth_traverse) {} + + GetValueOptions &DoCheckDotVsArrowSyntax() { + m_check_dot_vs_arrow_syntax = true; + return *this; + } + + GetValueOptions &DontCheckDotVsArrowSyntax() { + m_check_dot_vs_arrow_syntax = false; + return *this; + } + + GetValueOptions &DoAllowFragileIVar() { + m_no_fragile_ivar = false; + return *this; + } + + GetValueOptions &DontAllowFragileIVar() { + m_no_fragile_ivar = true; + return *this; + } + + GetValueOptions &DoAllowBitfieldSyntax() { + m_allow_bitfields_syntax = true; + return *this; + } + + GetValueOptions &DontAllowBitfieldSyntax() { + m_allow_bitfields_syntax = false; + return *this; + } + + GetValueOptions & + SetSyntheticChildrenTraversal(SyntheticChildrenTraversal traverse) { + m_synthetic_children_traversal = traverse; + return *this; + } + + static const GetValueOptions DefaultOptions() { + static GetValueOptions g_default_options; + + return g_default_options; + } + }; + + static lldb::ValueObjectSP + Parse(lldb::ValueObjectSP root, llvm::StringRef expression, + ScanEndReason *reason_to_stop, EndResultType *final_result, + const GetValueOptions &options, Aftermath *what_next); +}; + +} // namespace lldb_private + +#endif // LLDB_CORE_VALUEOBJECT_H Index: lldb/include/lldb/Core/ValueObject.h =================================================================== --- lldb/include/lldb/Core/ValueObject.h +++ lldb/include/lldb/Core/ValueObject.h @@ -9,6 +9,7 @@ #ifndef LLDB_CORE_VALUEOBJECT_H #define LLDB_CORE_VALUEOBJECT_H +#include "lldb/Core/ExpressionPath.h" #include "lldb/Core/Value.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Type.h" @@ -104,11 +105,6 @@ class ValueObject { public: - enum GetExpressionPathFormat { - eGetExpressionPathFormatDereferencePointers = 1, - eGetExpressionPathFormatHonorPointers - }; - enum ValueObjectRepresentationStyle { eValueObjectRepresentationStyleValue = 1, eValueObjectRepresentationStyleSummary, @@ -120,65 +116,6 @@ eValueObjectRepresentationStyleExpressionPath }; - enum ExpressionPathScanEndReason { - /// Out of data to parse. - eExpressionPathScanEndReasonEndOfString = 1, - /// Child element not found. - eExpressionPathScanEndReasonNoSuchChild, - /// (Synthetic) child element not found. - eExpressionPathScanEndReasonNoSuchSyntheticChild, - /// [] only allowed for arrays. - eExpressionPathScanEndReasonEmptyRangeNotAllowed, - /// . used when -> should be used. - eExpressionPathScanEndReasonDotInsteadOfArrow, - /// -> used when . should be used. - eExpressionPathScanEndReasonArrowInsteadOfDot, - /// ObjC ivar expansion not allowed. - eExpressionPathScanEndReasonFragileIVarNotAllowed, - /// [] not allowed by options. - eExpressionPathScanEndReasonRangeOperatorNotAllowed, - /// [] not valid on objects other than scalars, pointers or arrays. - eExpressionPathScanEndReasonRangeOperatorInvalid, - /// [] is good for arrays, but I cannot parse it. - eExpressionPathScanEndReasonArrayRangeOperatorMet, - /// [] is good for bitfields, but I cannot parse after it. - eExpressionPathScanEndReasonBitfieldRangeOperatorMet, - /// Something is malformed in he expression. - eExpressionPathScanEndReasonUnexpectedSymbol, - /// Impossible to apply & operator. - eExpressionPathScanEndReasonTakingAddressFailed, - /// Impossible to apply * operator. - eExpressionPathScanEndReasonDereferencingFailed, - /// [] was expanded into a VOList. - eExpressionPathScanEndReasonRangeOperatorExpanded, - /// getting the synthetic children failed. - eExpressionPathScanEndReasonSyntheticValueMissing, - eExpressionPathScanEndReasonUnknown = 0xFFFF - }; - - enum ExpressionPathEndResultType { - /// Anything but... - eExpressionPathEndResultTypePlain = 1, - /// A bitfield. - eExpressionPathEndResultTypeBitfield, - /// A range [low-high]. - eExpressionPathEndResultTypeBoundedRange, - /// A range []. - eExpressionPathEndResultTypeUnboundedRange, - /// Several items in a VOList. - eExpressionPathEndResultTypeValueObjectList, - eExpressionPathEndResultTypeInvalid = 0xFFFF - }; - - enum ExpressionPathAftermath { - /// Just return it. - eExpressionPathAftermathNothing = 1, - /// Dereference the target. - eExpressionPathAftermathDereference, - /// Take target's address. - eExpressionPathAftermathTakeAddress - }; - enum ClearUserVisibleDataItems { eClearUserVisibleDataItemsNothing = 1u << 0, eClearUserVisibleDataItemsValue = 1u << 1, @@ -193,70 +130,6 @@ eClearUserVisibleDataItemsAll = 0xFFFF }; - struct GetValueForExpressionPathOptions { - enum class SyntheticChildrenTraversal { - None, - ToSynthetic, - FromSynthetic, - Both - }; - - bool m_check_dot_vs_arrow_syntax; - bool m_no_fragile_ivar; - bool m_allow_bitfields_syntax; - SyntheticChildrenTraversal m_synthetic_children_traversal; - - GetValueForExpressionPathOptions( - bool dot = false, bool no_ivar = false, bool bitfield = true, - SyntheticChildrenTraversal synth_traverse = - SyntheticChildrenTraversal::ToSynthetic) - : m_check_dot_vs_arrow_syntax(dot), m_no_fragile_ivar(no_ivar), - m_allow_bitfields_syntax(bitfield), - m_synthetic_children_traversal(synth_traverse) {} - - GetValueForExpressionPathOptions &DoCheckDotVsArrowSyntax() { - m_check_dot_vs_arrow_syntax = true; - return *this; - } - - GetValueForExpressionPathOptions &DontCheckDotVsArrowSyntax() { - m_check_dot_vs_arrow_syntax = false; - return *this; - } - - GetValueForExpressionPathOptions &DoAllowFragileIVar() { - m_no_fragile_ivar = false; - return *this; - } - - GetValueForExpressionPathOptions &DontAllowFragileIVar() { - m_no_fragile_ivar = true; - return *this; - } - - GetValueForExpressionPathOptions &DoAllowBitfieldSyntax() { - m_allow_bitfields_syntax = true; - return *this; - } - - GetValueForExpressionPathOptions &DontAllowBitfieldSyntax() { - m_allow_bitfields_syntax = false; - return *this; - } - - GetValueForExpressionPathOptions & - SetSyntheticChildrenTraversal(SyntheticChildrenTraversal traverse) { - m_synthetic_children_traversal = traverse; - return *this; - } - - static const GetValueForExpressionPathOptions DefaultOptions() { - static GetValueForExpressionPathOptions g_default_options; - - return g_default_options; - } - }; - class EvaluationPoint { public: EvaluationPoint(); @@ -395,17 +268,18 @@ bool IsIntegerType(bool &is_signed); - virtual void GetExpressionPath( - Stream &s, - GetExpressionPathFormat = eGetExpressionPathFormatDereferencePointers); + virtual void + GetExpressionPath(Stream &s, + ExpressionPath::PathFormat = + ExpressionPath::PathFormat::DereferencePointers); lldb::ValueObjectSP GetValueForExpressionPath( llvm::StringRef expression, - ExpressionPathScanEndReason *reason_to_stop = nullptr, - ExpressionPathEndResultType *final_value_type = nullptr, - const GetValueForExpressionPathOptions &options = - GetValueForExpressionPathOptions::DefaultOptions(), - ExpressionPathAftermath *final_task_on_target = nullptr); + ExpressionPath::ScanEndReason *reason_to_stop = nullptr, + ExpressionPath::EndResultType *final_value_type = nullptr, + const ExpressionPath::GetValueOptions &options = + ExpressionPath::GetValueOptions::DefaultOptions(), + ExpressionPath::Aftermath *final_task_on_target = nullptr); virtual bool IsInScope() { return true; } @@ -988,13 +862,6 @@ GetRoot()->DoUpdateChildrenAddressType(*this); } - lldb::ValueObjectSP GetValueForExpressionPath_Impl( - llvm::StringRef expression_cstr, - ExpressionPathScanEndReason *reason_to_stop, - ExpressionPathEndResultType *final_value_type, - const GetValueForExpressionPathOptions &options, - ExpressionPathAftermath *final_task_on_target); - ValueObject(const ValueObject &) = delete; const ValueObject &operator=(const ValueObject &) = delete; }; Index: lldb/include/lldb/Core/ValueObjectRegister.h =================================================================== --- lldb/include/lldb/Core/ValueObjectRegister.h +++ lldb/include/lldb/Core/ValueObjectRegister.h @@ -102,10 +102,9 @@ bool ResolveValue(Scalar &scalar) override; - void - GetExpressionPath(Stream &s, - GetExpressionPathFormat epformat = - eGetExpressionPathFormatDereferencePointers) override; + void GetExpressionPath( + Stream &s, ExpressionPath::PathFormat epformat = + ExpressionPath::PathFormat::DereferencePointers) override; protected: bool UpdateValue() override; Index: lldb/source/Commands/CommandObjectFrame.cpp =================================================================== --- lldb/source/Commands/CommandObjectFrame.cpp +++ lldb/source/Commands/CommandObjectFrame.cpp @@ -169,8 +169,8 @@ [&valobj_sp](ConstString type, ConstString var, const DumpValueObjectOptions &opts, Stream &stream) -> bool { - const ValueObject::GetExpressionPathFormat format = ValueObject:: - GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers; + const ExpressionPath::PathFormat format = + ExpressionPath::PathFormat::HonorPointers; valobj_sp->GetExpressionPath(stream, format); stream.PutCString(" ="); return true; Index: lldb/source/Core/CMakeLists.txt =================================================================== --- lldb/source/Core/CMakeLists.txt +++ lldb/source/Core/CMakeLists.txt @@ -32,6 +32,7 @@ DumpRegisterValue.cpp DynamicLoader.cpp EmulateInstruction.cpp + ExpressionPath.cpp FileLineResolver.cpp FileSpecList.cpp FormatEntity.cpp Index: lldb/source/Core/ExpressionPath.cpp =================================================================== --- /dev/null +++ lldb/source/Core/ExpressionPath.cpp @@ -0,0 +1,474 @@ +//===-- ExpressionPath.cpp ------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/ExpressionPath.h" +#include "lldb/Core/ValueObject.h" + +using namespace lldb; +using namespace lldb_private; + +ValueObjectSP ExpressionPath::Parse(ValueObjectSP root, + llvm::StringRef expression, + ScanEndReason *reason_to_stop, + EndResultType *final_result, + const GetValueOptions &options, + Aftermath *what_next) { + + if (!root) + return nullptr; + + llvm::StringRef remainder = expression; + + while (true) { + llvm::StringRef temp_expression = remainder; + + CompilerType root_compiler_type = root->GetCompilerType(); + CompilerType pointee_compiler_type; + Flags pointee_compiler_type_info; + + Flags root_compiler_type_info( + root_compiler_type.GetTypeInfo(&pointee_compiler_type)); + if (pointee_compiler_type) + pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo()); + + if (temp_expression.empty()) { + *reason_to_stop = ScanEndReason::EndOfString; + return root; + } + + switch (temp_expression.front()) { + case '-': { + temp_expression = temp_expression.drop_front(); + if (options.m_check_dot_vs_arrow_syntax && + root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to + // use -> on a + // non-pointer and I + // must catch the error + { + *reason_to_stop = ScanEndReason::ArrowInsteadOfDot; + *final_result = EndResultType::Invalid; + return ValueObjectSP(); + } + if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to + // extract an ObjC IVar + // when this is forbidden + root_compiler_type_info.Test(eTypeIsPointer) && + options.m_no_fragile_ivar) { + *reason_to_stop = ScanEndReason::FragileIVarNotAllowed; + *final_result = EndResultType::Invalid; + return ValueObjectSP(); + } + if (!temp_expression.startswith(">")) { + *reason_to_stop = ScanEndReason::UnexpectedSymbol; + *final_result = EndResultType::Invalid; + return ValueObjectSP(); + } + } + LLVM_FALLTHROUGH; + case '.': // or fallthrough from -> + { + if (options.m_check_dot_vs_arrow_syntax && + temp_expression.front() == '.' && + root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to + // use . on a pointer + // and I must catch the + // error + { + *reason_to_stop = ScanEndReason::DotInsteadOfArrow; + *final_result = EndResultType::Invalid; + return nullptr; + } + temp_expression = temp_expression.drop_front(); // skip . or > + + size_t next_sep_pos = temp_expression.find_first_of("-.[", 1); + ConstString child_name; + if (next_sep_pos == llvm::StringRef::npos) // if no other separator just + // expand this last layer + { + child_name.SetString(temp_expression); + ValueObjectSP child_valobj_sp = + root->GetChildMemberWithName(child_name, true); + + if (child_valobj_sp.get()) // we know we are done, so just return + { + *reason_to_stop = ScanEndReason::EndOfString; + *final_result = EndResultType::Plain; + return child_valobj_sp; + } else { + switch (options.m_synthetic_children_traversal) { + case GetValueOptions::SyntheticChildrenTraversal::None: + break; + case GetValueOptions::SyntheticChildrenTraversal::FromSynthetic: + if (root->IsSynthetic()) { + child_valobj_sp = root->GetNonSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); + } + break; + case GetValueOptions::SyntheticChildrenTraversal::ToSynthetic: + if (!root->IsSynthetic()) { + child_valobj_sp = root->GetSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); + } + break; + case GetValueOptions::SyntheticChildrenTraversal::Both: + if (root->IsSynthetic()) { + child_valobj_sp = root->GetNonSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); + } else { + child_valobj_sp = root->GetSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); + } + break; + } + } + + // if we are here and options.m_no_synthetic_children is true, + // child_valobj_sp is going to be a NULL SP, so we hit the "else" + // branch, and return an error + if (child_valobj_sp.get()) // if it worked, just return + { + *reason_to_stop = ScanEndReason::EndOfString; + *final_result = EndResultType::Plain; + return child_valobj_sp; + } else { + *reason_to_stop = ScanEndReason::NoSuchChild; + *final_result = EndResultType::Invalid; + return nullptr; + } + } else // other layers do expand + { + llvm::StringRef next_separator = temp_expression.substr(next_sep_pos); + + child_name.SetString(temp_expression.slice(0, next_sep_pos)); + + ValueObjectSP child_valobj_sp = + root->GetChildMemberWithName(child_name, true); + if (child_valobj_sp.get()) // store the new root and move on + { + root = child_valobj_sp; + remainder = next_separator; + *final_result = EndResultType::Plain; + continue; + } else { + switch (options.m_synthetic_children_traversal) { + case GetValueOptions::SyntheticChildrenTraversal::None: + break; + case GetValueOptions::SyntheticChildrenTraversal::FromSynthetic: + if (root->IsSynthetic()) { + child_valobj_sp = root->GetNonSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); + } + break; + case GetValueOptions::SyntheticChildrenTraversal::ToSynthetic: + if (!root->IsSynthetic()) { + child_valobj_sp = root->GetSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); + } + break; + case GetValueOptions::SyntheticChildrenTraversal::Both: + if (root->IsSynthetic()) { + child_valobj_sp = root->GetNonSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); + } else { + child_valobj_sp = root->GetSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); + } + break; + } + } + + // if we are here and options.m_no_synthetic_children is true, + // child_valobj_sp is going to be a NULL SP, so we hit the "else" + // branch, and return an error + if (child_valobj_sp.get()) // if it worked, move on + { + root = child_valobj_sp; + remainder = next_separator; + *final_result = EndResultType::Plain; + continue; + } else { + *reason_to_stop = ScanEndReason::NoSuchChild; + *final_result = EndResultType::Invalid; + return nullptr; + } + } + break; + } + case '[': { + if (!root_compiler_type_info.Test(eTypeIsArray) && + !root_compiler_type_info.Test(eTypeIsPointer) && + !root_compiler_type_info.Test( + eTypeIsVector)) // if this is not a T[] nor a T* + { + if (!root_compiler_type_info.Test( + eTypeIsScalar)) // if this is not even a scalar... + { + if (options.m_synthetic_children_traversal == + GetValueOptions::SyntheticChildrenTraversal:: + None) // ...only chance left is synthetic + { + *reason_to_stop = ScanEndReason::RangeOperatorInvalid; + *final_result = EndResultType::Invalid; + return ValueObjectSP(); + } + } else if (!options.m_allow_bitfields_syntax) // if this is a scalar, + // check that we can + // expand bitfields + { + *reason_to_stop = ScanEndReason::RangeOperatorNotAllowed; + *final_result = EndResultType::Invalid; + return ValueObjectSP(); + } + } + if (temp_expression[1] == + ']') // if this is an unbounded range it only works for arrays + { + if (!root_compiler_type_info.Test(eTypeIsArray)) { + *reason_to_stop = ScanEndReason::EmptyRangeNotAllowed; + *final_result = EndResultType::Invalid; + return nullptr; + } else // even if something follows, we cannot expand unbounded ranges, + // just let the caller do it + { + *reason_to_stop = ScanEndReason::ArrayRangeOperatorMet; + *final_result = EndResultType::UnboundedRange; + return root; + } + } + + size_t close_bracket_position = temp_expression.find(']', 1); + if (close_bracket_position == + llvm::StringRef::npos) // if there is no ], this is a syntax error + { + *reason_to_stop = ScanEndReason::UnexpectedSymbol; + *final_result = EndResultType::Invalid; + return nullptr; + } + + llvm::StringRef bracket_expr = + temp_expression.slice(1, close_bracket_position); + + // If this was an empty expression it would have been caught by the if + // above. + assert(!bracket_expr.empty()); + + if (!bracket_expr.contains('-')) { + // if no separator, this is of the form [N]. Note that this cannot be + // an unbounded range of the form [], because that case was handled + // above with an unconditional return. + unsigned long index = 0; + if (bracket_expr.getAsInteger(0, index)) { + *reason_to_stop = ScanEndReason::UnexpectedSymbol; + *final_result = EndResultType::Invalid; + return nullptr; + } + + // from here on we do have a valid index + if (root_compiler_type_info.Test(eTypeIsArray)) { + ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true); + if (!child_valobj_sp) + child_valobj_sp = root->GetSyntheticArrayMember(index, true); + if (!child_valobj_sp) + if (root->HasSyntheticValue() && + root->GetSyntheticValue()->GetNumChildren() > index) + child_valobj_sp = + root->GetSyntheticValue()->GetChildAtIndex(index, true); + if (child_valobj_sp) { + root = child_valobj_sp; + remainder = + temp_expression.substr(close_bracket_position + 1); // skip ] + *final_result = EndResultType::Plain; + continue; + } else { + *reason_to_stop = ScanEndReason::NoSuchChild; + *final_result = EndResultType::Invalid; + return nullptr; + } + } else if (root_compiler_type_info.Test(eTypeIsPointer)) { + if (*what_next == Aftermath::Dereference && // if this is a + // ptr-to-scalar, I + // am accessing it + // by index and I + // would have + // deref'ed anyway, + // then do it now + // and use this as + // a bitfield + pointee_compiler_type_info.Test(eTypeIsScalar)) { + Status error; + root = root->Dereference(error); + if (error.Fail() || !root) { + *reason_to_stop = ScanEndReason::DereferencingFailed; + *final_result = EndResultType::Invalid; + return nullptr; + } else { + *what_next = Aftermath::Nothing; + continue; + } + } else { + if (root->GetCompilerType().GetMinimumLanguage() == + eLanguageTypeObjC && + pointee_compiler_type_info.AllClear(eTypeIsPointer) && + root->HasSyntheticValue() && + (options.m_synthetic_children_traversal == + GetValueOptions::SyntheticChildrenTraversal::ToSynthetic || + options.m_synthetic_children_traversal == + GetValueOptions::SyntheticChildrenTraversal::Both)) { + root = root->GetSyntheticValue()->GetChildAtIndex(index, true); + } else + root = root->GetSyntheticArrayMember(index, true); + if (!root) { + *reason_to_stop = ScanEndReason::NoSuchChild; + *final_result = EndResultType::Invalid; + return nullptr; + } else { + remainder = + temp_expression.substr(close_bracket_position + 1); // skip ] + *final_result = EndResultType::Plain; + continue; + } + } + } else if (root_compiler_type_info.Test(eTypeIsScalar)) { + root = root->GetSyntheticBitFieldChild(index, index, true); + if (!root) { + *reason_to_stop = ScanEndReason::NoSuchChild; + *final_result = EndResultType::Invalid; + return nullptr; + } else // we do not know how to expand members of bitfields, so we + // just return and let the caller do any further processing + { + *reason_to_stop = ScanEndReason::BitfieldRangeOperatorMet; + *final_result = EndResultType::Bitfield; + return root; + } + } else if (root_compiler_type_info.Test(eTypeIsVector)) { + root = root->GetChildAtIndex(index, true); + if (!root) { + *reason_to_stop = ScanEndReason::NoSuchChild; + *final_result = EndResultType::Invalid; + return ValueObjectSP(); + } else { + remainder = + temp_expression.substr(close_bracket_position + 1); // skip ] + *final_result = EndResultType::Plain; + continue; + } + } else if (options.m_synthetic_children_traversal == + GetValueOptions::SyntheticChildrenTraversal:: + ToSynthetic || + options.m_synthetic_children_traversal == + GetValueOptions::SyntheticChildrenTraversal::Both) { + if (root->HasSyntheticValue()) + root = root->GetSyntheticValue(); + else if (!root->IsSynthetic()) { + *reason_to_stop = ScanEndReason::SyntheticValueMissing; + *final_result = EndResultType::Invalid; + return nullptr; + } + // if we are here, then root itself is a synthetic VO.. should be + // good to go + + if (!root) { + *reason_to_stop = ScanEndReason::SyntheticValueMissing; + *final_result = EndResultType::Invalid; + return nullptr; + } + root = root->GetChildAtIndex(index, true); + if (!root) { + *reason_to_stop = ScanEndReason::NoSuchChild; + *final_result = EndResultType::Invalid; + return nullptr; + } else { + remainder = + temp_expression.substr(close_bracket_position + 1); // skip ] + *final_result = EndResultType::Plain; + continue; + } + } else { + *reason_to_stop = ScanEndReason::NoSuchChild; + *final_result = EndResultType::Invalid; + return nullptr; + } + } else { + // we have a low and a high index + llvm::StringRef sleft, sright; + unsigned long low_index, high_index; + std::tie(sleft, sright) = bracket_expr.split('-'); + if (sleft.getAsInteger(0, low_index) || + sright.getAsInteger(0, high_index)) { + *reason_to_stop = ScanEndReason::UnexpectedSymbol; + *final_result = EndResultType::Invalid; + return nullptr; + } + + if (low_index > high_index) // swap indices if required + std::swap(low_index, high_index); + + if (root_compiler_type_info.Test( + eTypeIsScalar)) // expansion only works for scalars + { + root = root->GetSyntheticBitFieldChild(low_index, high_index, true); + if (!root) { + *reason_to_stop = ScanEndReason::NoSuchChild; + *final_result = EndResultType::Invalid; + return nullptr; + } else { + *reason_to_stop = ScanEndReason::BitfieldRangeOperatorMet; + *final_result = EndResultType::Bitfield; + return root; + } + } else if (root_compiler_type_info.Test( + eTypeIsPointer) && // if this is a ptr-to-scalar, I am + // accessing it by index and I would + // have deref'ed anyway, then do it + // now and use this as a bitfield + *what_next == Aftermath::Dereference && + pointee_compiler_type_info.Test(eTypeIsScalar)) { + Status error; + root = root->Dereference(error); + if (error.Fail() || !root) { + *reason_to_stop = ScanEndReason::DereferencingFailed; + *final_result = EndResultType::Invalid; + return nullptr; + } else { + *what_next = ExpressionPath::Aftermath::Nothing; + continue; + } + } else { + *reason_to_stop = ScanEndReason::ArrayRangeOperatorMet; + *final_result = EndResultType::BoundedRange; + return root; + } + } + break; + } + default: // some non-separator is in the way + { + *reason_to_stop = ScanEndReason::UnexpectedSymbol; + *final_result = EndResultType::Invalid; + return nullptr; + } + } + } +} Index: lldb/source/Core/FormatEntity.cpp =================================================================== --- lldb/source/Core/FormatEntity.cpp +++ lldb/source/Core/FormatEntity.cpp @@ -632,12 +632,12 @@ ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); LLDB_LOGF(log, "[ExpandIndexedExpression] name to deref: %s", ptr_deref_buffer.c_str()); - ValueObject::GetValueForExpressionPathOptions options; - ValueObject::ExpressionPathEndResultType final_value_type; - ValueObject::ExpressionPathScanEndReason reason_to_stop; - ValueObject::ExpressionPathAftermath what_next = - (deref_pointer ? ValueObject::eExpressionPathAftermathDereference - : ValueObject::eExpressionPathAftermathNothing); + ExpressionPath::GetValueOptions options; + ExpressionPath::EndResultType final_value_type; + ExpressionPath::ScanEndReason reason_to_stop; + ExpressionPath::Aftermath what_next = + (deref_pointer ? ExpressionPath::Aftermath::Dereference + : ExpressionPath::Aftermath::Nothing); ValueObjectSP item = valobj->GetValueForExpressionPath( ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options, &what_next); @@ -723,16 +723,15 @@ if (valobj == nullptr) return false; - ValueObject::ExpressionPathAftermath what_next = - (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference - : ValueObject::eExpressionPathAftermathNothing); - ValueObject::GetValueForExpressionPathOptions options; + ExpressionPath::Aftermath what_next = + (do_deref_pointer ? ExpressionPath::Aftermath::Dereference + : ExpressionPath::Aftermath::Nothing); + ExpressionPath::GetValueOptions options; options.DontCheckDotVsArrowSyntax() .DoAllowBitfieldSyntax() .DoAllowFragileIVar() .SetSyntheticChildrenTraversal( - ValueObject::GetValueForExpressionPathOptions:: - SyntheticChildrenTraversal::Both); + ExpressionPath::GetValueOptions::SyntheticChildrenTraversal::Both); ValueObject *target = nullptr; const char *var_name_final_if_array_range = nullptr; size_t close_bracket_index = llvm::StringRef::npos; @@ -742,10 +741,10 @@ bool was_plain_var = false; bool was_var_format = false; bool was_var_indexed = false; - ValueObject::ExpressionPathScanEndReason reason_to_stop = - ValueObject::eExpressionPathScanEndReasonEndOfString; - ValueObject::ExpressionPathEndResultType final_value_type = - ValueObject::eExpressionPathEndResultTypePlain; + ExpressionPath::ScanEndReason reason_to_stop = + ExpressionPath::ScanEndReason::EndOfString; + ExpressionPath::EndResultType final_value_type = + ExpressionPath::EndResultType::Plain; if (is_script) { return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str()); @@ -800,13 +799,10 @@ } is_array_range = - (final_value_type == - ValueObject::eExpressionPathEndResultTypeBoundedRange || - final_value_type == - ValueObject::eExpressionPathEndResultTypeUnboundedRange); + (final_value_type == ExpressionPath::EndResultType::BoundedRange || + final_value_type == ExpressionPath::EndResultType::UnboundedRange); - do_deref_pointer = - (what_next == ValueObject::eExpressionPathAftermathDereference); + do_deref_pointer = (what_next == ExpressionPath::Aftermath::Dereference); if (do_deref_pointer && !is_array_range) { // I have not deref-ed yet, let's do it Index: lldb/source/Core/ValueObject.cpp =================================================================== --- lldb/source/Core/ValueObject.cpp +++ lldb/source/Core/ValueObject.cpp @@ -1835,9 +1835,8 @@ // make one and cache it for any future reference. synthetic_child_sp = GetValueForExpressionPath( expression, nullptr, nullptr, - GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal( - GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: - None)); + ExpressionPath::GetValueOptions().SetSyntheticChildrenTraversal( + ExpressionPath::GetValueOptions::SyntheticChildrenTraversal::None)); // Cache the value if we got one back... if (synthetic_child_sp.get()) { @@ -1949,7 +1948,7 @@ } void ValueObject::GetExpressionPath(Stream &s, - GetExpressionPathFormat epformat) { + ExpressionPath::PathFormat epformat) { // synthetic children do not actually "exist" as part of the hierarchy, and // sometimes they are consed up in ways that don't make sense from an // underlying language/API standpoint. So, use a special code path here to @@ -1985,7 +1984,7 @@ const bool is_deref_of_parent = IsDereferenceOfParent(); if (is_deref_of_parent && - epformat == eGetExpressionPathFormatDereferencePointers) { + epformat == ExpressionPath::PathFormat::DereferencePointers) { // this is the original format of GetExpressionPath() producing code like // *(a_ptr).memberName, which is entirely fine, until you put this into // StackFrame::GetValueForVariableExpressionPath() which prefers to see @@ -2003,7 +2002,7 @@ // made up to allow ptr[%d] syntax to work in variable printing, then add our // name ([%d]) to the expression path if (m_flags.m_is_array_item_for_pointer && - epformat == eGetExpressionPathFormatHonorPointers) + epformat == ExpressionPath::PathFormat::HonorPointers) s.PutCString(m_name.GetStringRef()); if (!IsBaseClass()) { @@ -2015,7 +2014,7 @@ non_base_class_parent->GetCompilerType(); if (non_base_class_parent_compiler_type) { if (parent && parent->IsDereferenceOfParent() && - epformat == eGetExpressionPathFormatHonorPointers) { + epformat == ExpressionPath::PathFormat::HonorPointers) { s.PutCString("->"); } else { const uint32_t non_base_class_parent_type_info = @@ -2038,71 +2037,68 @@ } if (is_deref_of_parent && - epformat == eGetExpressionPathFormatDereferencePointers) { + epformat == ExpressionPath::PathFormat::DereferencePointers) { s.PutChar(')'); } } - ValueObjectSP ValueObject::GetValueForExpressionPath( - llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop, - ExpressionPathEndResultType *final_value_type, - const GetValueForExpressionPathOptions &options, - ExpressionPathAftermath *final_task_on_target) { - - ExpressionPathScanEndReason dummy_reason_to_stop = - ValueObject::eExpressionPathScanEndReasonUnknown; - ExpressionPathEndResultType dummy_final_value_type = - ValueObject::eExpressionPathEndResultTypeInvalid; - ExpressionPathAftermath dummy_final_task_on_target = - ValueObject::eExpressionPathAftermathNothing; - - ValueObjectSP ret_val = GetValueForExpressionPath_Impl( - expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, + llvm::StringRef expression, ExpressionPath::ScanEndReason *reason_to_stop, + ExpressionPath::EndResultType *final_value_type, + const ExpressionPath::GetValueOptions &options, + ExpressionPath::Aftermath *final_task_on_target) { + + ExpressionPath::ScanEndReason dummy_reason_to_stop = + ExpressionPath::ScanEndReason::Unknown; + ExpressionPath::EndResultType dummy_final_value_type = + ExpressionPath::EndResultType::Invalid; + ExpressionPath::Aftermath dummy_final_task_on_target = + ExpressionPath::Aftermath::Nothing; + + ValueObjectSP ret_val = ExpressionPath::Parse( + GetSP(), expression, + reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, final_value_type ? final_value_type : &dummy_final_value_type, options, final_task_on_target ? final_task_on_target : &dummy_final_task_on_target); if (!final_task_on_target || - *final_task_on_target == ValueObject::eExpressionPathAftermathNothing) + *final_task_on_target == ExpressionPath::Aftermath::Nothing) return ret_val; if (ret_val.get() && ((final_value_type ? *final_value_type : dummy_final_value_type) == - eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress - // of plain objects + ExpressionPath::EndResultType::Plain)) // I can only deref and + // takeaddress of plain objects { if ((final_task_on_target ? *final_task_on_target : dummy_final_task_on_target) == - ValueObject::eExpressionPathAftermathDereference) { + ExpressionPath::Aftermath::Dereference) { Status error; ValueObjectSP final_value = ret_val->Dereference(error); if (error.Fail() || !final_value.get()) { if (reason_to_stop) - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonDereferencingFailed; + *reason_to_stop = ExpressionPath::ScanEndReason::DereferencingFailed; if (final_value_type) - *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; + *final_value_type = ExpressionPath::EndResultType::Invalid; return ValueObjectSP(); } else { if (final_task_on_target) - *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; + *final_task_on_target = ExpressionPath::Aftermath::Nothing; return final_value; } } - if (*final_task_on_target == - ValueObject::eExpressionPathAftermathTakeAddress) { + if (*final_task_on_target == ExpressionPath::Aftermath::TakeAddress) { Status error; ValueObjectSP final_value = ret_val->AddressOf(error); if (error.Fail() || !final_value.get()) { if (reason_to_stop) - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonTakingAddressFailed; + *reason_to_stop = ExpressionPath::ScanEndReason::TakingAddressFailed; if (final_value_type) - *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; + *final_value_type = ExpressionPath::EndResultType::Invalid; return ValueObjectSP(); } else { if (final_task_on_target) - *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; + *final_task_on_target = ExpressionPath::Aftermath::Nothing; return final_value; } } @@ -2111,512 +2107,6 @@ // you know I did not do it } -ValueObjectSP ValueObject::GetValueForExpressionPath_Impl( - llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop, - ExpressionPathEndResultType *final_result, - const GetValueForExpressionPathOptions &options, - ExpressionPathAftermath *what_next) { - ValueObjectSP root = GetSP(); - - if (!root) - return nullptr; - - llvm::StringRef remainder = expression; - - while (true) { - llvm::StringRef temp_expression = remainder; - - CompilerType root_compiler_type = root->GetCompilerType(); - CompilerType pointee_compiler_type; - Flags pointee_compiler_type_info; - - Flags root_compiler_type_info( - root_compiler_type.GetTypeInfo(&pointee_compiler_type)); - if (pointee_compiler_type) - pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo()); - - if (temp_expression.empty()) { - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; - return root; - } - - switch (temp_expression.front()) { - case '-': { - temp_expression = temp_expression.drop_front(); - if (options.m_check_dot_vs_arrow_syntax && - root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to - // use -> on a - // non-pointer and I - // must catch the error - { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to - // extract an ObjC IVar - // when this is forbidden - root_compiler_type_info.Test(eTypeIsPointer) && - options.m_no_fragile_ivar) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - if (!temp_expression.startswith(">")) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - } - LLVM_FALLTHROUGH; - case '.': // or fallthrough from -> - { - if (options.m_check_dot_vs_arrow_syntax && - temp_expression.front() == '.' && - root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to - // use . on a pointer - // and I must catch the - // error - { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } - temp_expression = temp_expression.drop_front(); // skip . or > - - size_t next_sep_pos = temp_expression.find_first_of("-.[", 1); - ConstString child_name; - if (next_sep_pos == llvm::StringRef::npos) // if no other separator just - // expand this last layer - { - child_name.SetString(temp_expression); - ValueObjectSP child_valobj_sp = - root->GetChildMemberWithName(child_name, true); - - if (child_valobj_sp.get()) // we know we are done, so just return - { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonEndOfString; - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - return child_valobj_sp; - } else { - switch (options.m_synthetic_children_traversal) { - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: - None: - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: - FromSynthetic: - if (root->IsSynthetic()) { - child_valobj_sp = root->GetNonSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = - child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: - ToSynthetic: - if (!root->IsSynthetic()) { - child_valobj_sp = root->GetSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = - child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: - Both: - if (root->IsSynthetic()) { - child_valobj_sp = root->GetNonSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = - child_valobj_sp->GetChildMemberWithName(child_name, true); - } else { - child_valobj_sp = root->GetSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = - child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - } - } - - // if we are here and options.m_no_synthetic_children is true, - // child_valobj_sp is going to be a NULL SP, so we hit the "else" - // branch, and return an error - if (child_valobj_sp.get()) // if it worked, just return - { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonEndOfString; - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - return child_valobj_sp; - } else { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } - } else // other layers do expand - { - llvm::StringRef next_separator = temp_expression.substr(next_sep_pos); - - child_name.SetString(temp_expression.slice(0, next_sep_pos)); - - ValueObjectSP child_valobj_sp = - root->GetChildMemberWithName(child_name, true); - if (child_valobj_sp.get()) // store the new root and move on - { - root = child_valobj_sp; - remainder = next_separator; - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } else { - switch (options.m_synthetic_children_traversal) { - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: - None: - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: - FromSynthetic: - if (root->IsSynthetic()) { - child_valobj_sp = root->GetNonSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = - child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: - ToSynthetic: - if (!root->IsSynthetic()) { - child_valobj_sp = root->GetSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = - child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: - Both: - if (root->IsSynthetic()) { - child_valobj_sp = root->GetNonSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = - child_valobj_sp->GetChildMemberWithName(child_name, true); - } else { - child_valobj_sp = root->GetSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = - child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - } - } - - // if we are here and options.m_no_synthetic_children is true, - // child_valobj_sp is going to be a NULL SP, so we hit the "else" - // branch, and return an error - if (child_valobj_sp.get()) // if it worked, move on - { - root = child_valobj_sp; - remainder = next_separator; - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } else { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } - } - break; - } - case '[': { - if (!root_compiler_type_info.Test(eTypeIsArray) && - !root_compiler_type_info.Test(eTypeIsPointer) && - !root_compiler_type_info.Test( - eTypeIsVector)) // if this is not a T[] nor a T* - { - if (!root_compiler_type_info.Test( - eTypeIsScalar)) // if this is not even a scalar... - { - if (options.m_synthetic_children_traversal == - GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: - None) // ...only chance left is synthetic - { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - } else if (!options.m_allow_bitfields_syntax) // if this is a scalar, - // check that we can - // expand bitfields - { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - } - if (temp_expression[1] == - ']') // if this is an unbounded range it only works for arrays - { - if (!root_compiler_type_info.Test(eTypeIsArray)) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } else // even if something follows, we cannot expand unbounded ranges, - // just let the caller do it - { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; - *final_result = - ValueObject::eExpressionPathEndResultTypeUnboundedRange; - return root; - } - } - - size_t close_bracket_position = temp_expression.find(']', 1); - if (close_bracket_position == - llvm::StringRef::npos) // if there is no ], this is a syntax error - { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } - - llvm::StringRef bracket_expr = - temp_expression.slice(1, close_bracket_position); - - // If this was an empty expression it would have been caught by the if - // above. - assert(!bracket_expr.empty()); - - if (!bracket_expr.contains('-')) { - // if no separator, this is of the form [N]. Note that this cannot be - // an unbounded range of the form [], because that case was handled - // above with an unconditional return. - unsigned long index = 0; - if (bracket_expr.getAsInteger(0, index)) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } - - // from here on we do have a valid index - if (root_compiler_type_info.Test(eTypeIsArray)) { - ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true); - if (!child_valobj_sp) - child_valobj_sp = root->GetSyntheticArrayMember(index, true); - if (!child_valobj_sp) - if (root->HasSyntheticValue() && - root->GetSyntheticValue()->GetNumChildren() > index) - child_valobj_sp = - root->GetSyntheticValue()->GetChildAtIndex(index, true); - if (child_valobj_sp) { - root = child_valobj_sp; - remainder = - temp_expression.substr(close_bracket_position + 1); // skip ] - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } else { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } - } else if (root_compiler_type_info.Test(eTypeIsPointer)) { - if (*what_next == - ValueObject:: - eExpressionPathAftermathDereference && // if this is a - // ptr-to-scalar, I - // am accessing it - // by index and I - // would have - // deref'ed anyway, - // then do it now - // and use this as - // a bitfield - pointee_compiler_type_info.Test(eTypeIsScalar)) { - Status error; - root = root->Dereference(error); - if (error.Fail() || !root) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonDereferencingFailed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } else { - *what_next = eExpressionPathAftermathNothing; - continue; - } - } else { - if (root->GetCompilerType().GetMinimumLanguage() == - eLanguageTypeObjC && - pointee_compiler_type_info.AllClear(eTypeIsPointer) && - root->HasSyntheticValue() && - (options.m_synthetic_children_traversal == - GetValueForExpressionPathOptions:: - SyntheticChildrenTraversal::ToSynthetic || - options.m_synthetic_children_traversal == - GetValueForExpressionPathOptions:: - SyntheticChildrenTraversal::Both)) { - root = root->GetSyntheticValue()->GetChildAtIndex(index, true); - } else - root = root->GetSyntheticArrayMember(index, true); - if (!root) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } else { - remainder = - temp_expression.substr(close_bracket_position + 1); // skip ] - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } - } - } else if (root_compiler_type_info.Test(eTypeIsScalar)) { - root = root->GetSyntheticBitFieldChild(index, index, true); - if (!root) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } else // we do not know how to expand members of bitfields, so we - // just return and let the caller do any further processing - { - *reason_to_stop = ValueObject:: - eExpressionPathScanEndReasonBitfieldRangeOperatorMet; - *final_result = ValueObject::eExpressionPathEndResultTypeBitfield; - return root; - } - } else if (root_compiler_type_info.Test(eTypeIsVector)) { - root = root->GetChildAtIndex(index, true); - if (!root) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } else { - remainder = - temp_expression.substr(close_bracket_position + 1); // skip ] - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } - } else if (options.m_synthetic_children_traversal == - GetValueForExpressionPathOptions:: - SyntheticChildrenTraversal::ToSynthetic || - options.m_synthetic_children_traversal == - GetValueForExpressionPathOptions:: - SyntheticChildrenTraversal::Both) { - if (root->HasSyntheticValue()) - root = root->GetSyntheticValue(); - else if (!root->IsSynthetic()) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } - // if we are here, then root itself is a synthetic VO.. should be - // good to go - - if (!root) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } - root = root->GetChildAtIndex(index, true); - if (!root) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } else { - remainder = - temp_expression.substr(close_bracket_position + 1); // skip ] - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } - } else { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } - } else { - // we have a low and a high index - llvm::StringRef sleft, sright; - unsigned long low_index, high_index; - std::tie(sleft, sright) = bracket_expr.split('-'); - if (sleft.getAsInteger(0, low_index) || - sright.getAsInteger(0, high_index)) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } - - if (low_index > high_index) // swap indices if required - std::swap(low_index, high_index); - - if (root_compiler_type_info.Test( - eTypeIsScalar)) // expansion only works for scalars - { - root = root->GetSyntheticBitFieldChild(low_index, high_index, true); - if (!root) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } else { - *reason_to_stop = ValueObject:: - eExpressionPathScanEndReasonBitfieldRangeOperatorMet; - *final_result = ValueObject::eExpressionPathEndResultTypeBitfield; - return root; - } - } else if (root_compiler_type_info.Test( - eTypeIsPointer) && // if this is a ptr-to-scalar, I am - // accessing it by index and I would - // have deref'ed anyway, then do it - // now and use this as a bitfield - *what_next == - ValueObject::eExpressionPathAftermathDereference && - pointee_compiler_type_info.Test(eTypeIsScalar)) { - Status error; - root = root->Dereference(error); - if (error.Fail() || !root) { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonDereferencingFailed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } else { - *what_next = ValueObject::eExpressionPathAftermathNothing; - continue; - } - } else { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; - *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange; - return root; - } - } - break; - } - default: // some non-separator is in the way - { - *reason_to_stop = - ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return nullptr; - } - } - } -} - void ValueObject::Dump(Stream &s) { Dump(s, DumpValueObjectOptions(*this)); } void ValueObject::Dump(Stream &s, const DumpValueObjectOptions &options) { Index: lldb/source/Core/ValueObjectRegister.cpp =================================================================== --- lldb/source/Core/ValueObjectRegister.cpp +++ lldb/source/Core/ValueObjectRegister.cpp @@ -299,7 +299,7 @@ return false; } -void ValueObjectRegister::GetExpressionPath(Stream &s, - GetExpressionPathFormat epformat) { +void ValueObjectRegister::GetExpressionPath( + Stream &s, ExpressionPath::PathFormat epformat) { s.Printf("$%s", m_reg_info.name); } Index: lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp =================================================================== --- lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -236,10 +236,10 @@ m_pair_ptr = valobj_sp ->GetValueForExpressionPath( ".__i_.__ptr_->__value_", nullptr, nullptr, - ValueObject::GetValueForExpressionPathOptions() + ExpressionPath::GetValueOptions() .DontCheckDotVsArrowSyntax() .SetSyntheticChildrenTraversal( - ValueObject::GetValueForExpressionPathOptions:: + ExpressionPath::GetValueOptions:: SyntheticChildrenTraversal::None), nullptr) .get(); @@ -248,10 +248,10 @@ m_pair_ptr = valobj_sp ->GetValueForExpressionPath( ".__i_.__ptr_", nullptr, nullptr, - ValueObject::GetValueForExpressionPathOptions() + ExpressionPath::GetValueOptions() .DontCheckDotVsArrowSyntax() .SetSyntheticChildrenTraversal( - ValueObject::GetValueForExpressionPathOptions:: + ExpressionPath::GetValueOptions:: SyntheticChildrenTraversal::None), nullptr) .get(); Index: lldb/source/Target/Process.cpp =================================================================== --- lldb/source/Target/Process.cpp +++ lldb/source/Target/Process.cpp @@ -859,9 +859,8 @@ ValueObjectSP valobj_sp = StopInfo::GetCrashingDereference( curr_thread_stop_info_sp, &crashing_address); if (valobj_sp) { - const ValueObject::GetExpressionPathFormat format = - ValueObject::GetExpressionPathFormat:: - eGetExpressionPathFormatHonorPointers; + const ExpressionPath::PathFormat format = + ExpressionPath::PathFormat::HonorPointers; stream->PutCString("Likely cause: "); valobj_sp->GetExpressionPath(*stream, format); stream->Printf(" accessed 0x%" PRIx64 "\n", crashing_address);