CompilerType GoUserExpression::GoInterpreter::EvaluateType(const GoASTExpr *e) { TargetSP target = m_exe_ctx.GetTargetSP(); if (auto *id = llvm::dyn_cast<GoASTIdent>(e)) { CompilerType result = LookupType(target, ConstString(id->GetName().m_value)); if (result.IsValid()) return result; std::string fullname = (m_package + "." + id->GetName().m_value).str(); result = LookupType(target, ConstString(fullname)); if (!result) m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str()); return result; } if (auto *sel = llvm::dyn_cast<GoASTSelectorExpr>(e)) { std::string package; if (auto *pkg_node = llvm::dyn_cast<GoASTIdent>(sel->GetX())) { package = pkg_node->GetName().m_value.str(); } else if (auto *str_node = llvm::dyn_cast<GoASTBasicLit>(sel->GetX())) { if (str_node->GetValue().m_type == GoLexer::LIT_STRING) { package = str_node->GetValue().m_value.substr(1).str(); package.resize(package.length() - 1); } } if (package.empty()) { m_error.SetErrorStringWithFormat("Invalid %s in type expression", sel->GetX()->GetKindName()); return CompilerType(); } std::string fullname = (package + "." + sel->GetSel()->GetName().m_value).str(); CompilerType result = LookupType(target, ConstString(fullname)); if (!result) m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str()); return result; } if (auto *star = llvm::dyn_cast<GoASTStarExpr>(e)) { CompilerType elem = EvaluateType(star->GetX()); return elem.GetPointerType(); } if (auto *paren = llvm::dyn_cast<GoASTParenExpr>(e)) return EvaluateType(paren->GetX()); if (auto *array = llvm::dyn_cast<GoASTArrayType>(e)) { CompilerType elem = EvaluateType(array->GetElt()); } m_error.SetErrorStringWithFormat("Invalid %s in type expression", e->GetKindName()); return CompilerType(); }
bool lldb_private::formatters::swift::SwiftOptionSetSummaryProvider:: WouldEvenConsiderFormatting(CompilerType clang_type) { SwiftASTContext *swift_ast_ctx = llvm::dyn_cast_or_null<SwiftASTContext>(clang_type.GetTypeSystem()); if (!swift_ast_ctx) return false; return clang_type.IsValid() && swift_ast_ctx->IsTrivialOptionSetType(clang_type) && swift_ast_ctx->IsImportedType(clang_type, nullptr); }
ValueObjectSP ABI::GetReturnValueObject(Thread &thread, CompilerType &ast_type, bool persistent) const { if (!ast_type.IsValid()) return ValueObjectSP(); ValueObjectSP return_valobj_sp; return_valobj_sp = GetReturnValueObjectImpl(thread, ast_type); if (!return_valobj_sp) return return_valobj_sp; // Now turn this into a persistent variable. // FIXME: This code is duplicated from Target::EvaluateExpression, and it is // used in similar form in a couple // of other places. Figure out the correct Create function to do all this // work. if (persistent) { PersistentExpressionState *persistent_expression_state = thread.CalculateTarget()->GetPersistentExpressionStateForLanguage( ast_type.GetMinimumLanguage()); if (!persistent_expression_state) return ValueObjectSP(); ConstString persistent_variable_name( persistent_expression_state->GetNextPersistentVariableName()); lldb::ValueObjectSP const_valobj_sp; // Check in case our value is already a constant value if (return_valobj_sp->GetIsConstant()) { const_valobj_sp = return_valobj_sp; const_valobj_sp->SetName(persistent_variable_name); } else const_valobj_sp = return_valobj_sp->CreateConstantValue(persistent_variable_name); lldb::ValueObjectSP live_valobj_sp = return_valobj_sp; return_valobj_sp = const_valobj_sp; ExpressionVariableSP clang_expr_variable_sp( persistent_expression_state->CreatePersistentVariable( return_valobj_sp)); assert(clang_expr_variable_sp); // Set flags and live data as appropriate const Value &result_value = live_valobj_sp->GetValue(); switch (result_value.GetValueType()) { case Value::eValueTypeHostAddress: case Value::eValueTypeFileAddress: // we don't do anything with these for now break; case Value::eValueTypeScalar: case Value::eValueTypeVector: clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried; clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation; break; case Value::eValueTypeLoadAddress: clang_expr_variable_sp->m_live_sp = live_valobj_sp; clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference; break; } return_valobj_sp = clang_expr_variable_sp->GetValueObject(); } return return_valobj_sp; }
static void PrivateAutoComplete (StackFrame *frame, const std::string &partial_path, const std::string &prefix_path, // Anything that has been resolved already will be in here const CompilerType& compiler_type, StringList &matches, bool &word_complete) { // printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path = '%s'\n", prefix_path.c_str(), partial_path.c_str()); std::string remaining_partial_path; const lldb::TypeClass type_class = compiler_type.GetTypeClass(); if (partial_path.empty()) { if (compiler_type.IsValid()) { switch (type_class) { default: case eTypeClassArray: case eTypeClassBlockPointer: case eTypeClassBuiltin: case eTypeClassComplexFloat: case eTypeClassComplexInteger: case eTypeClassEnumeration: case eTypeClassFunction: case eTypeClassMemberPointer: case eTypeClassReference: case eTypeClassTypedef: case eTypeClassVector: { matches.AppendString (prefix_path); word_complete = matches.GetSize() == 1; } break; case eTypeClassClass: case eTypeClassStruct: case eTypeClassUnion: if (prefix_path.back() != '.') matches.AppendString (prefix_path + '.'); break; case eTypeClassObjCObject: case eTypeClassObjCInterface: break; case eTypeClassObjCObjectPointer: case eTypeClassPointer: { bool omit_empty_base_classes = true; if (compiler_type.GetNumChildren (omit_empty_base_classes) > 0) matches.AppendString (prefix_path + "->"); else { matches.AppendString (prefix_path); word_complete = true; } } break; } } else { if (frame) { const bool get_file_globals = true; VariableList *variable_list = frame->GetVariableList(get_file_globals); if (variable_list) { const size_t num_variables = variable_list->GetSize(); for (size_t i=0; i<num_variables; ++i) { Variable *variable = variable_list->GetVariableAtIndex(i).get(); matches.AppendString (variable->GetName().AsCString()); } } } } } else { const char ch = partial_path[0]; switch (ch) { case '*': if (prefix_path.empty()) { PrivateAutoComplete (frame, partial_path.substr(1), std::string("*"), compiler_type, matches, word_complete); } break; case '&': if (prefix_path.empty()) { PrivateAutoComplete (frame, partial_path.substr(1), std::string("&"), compiler_type, matches, word_complete); } break; case '-': if (partial_path[1] == '>' && !prefix_path.empty()) { switch (type_class) { case lldb::eTypeClassPointer: { CompilerType pointee_type(compiler_type.GetPointeeType()); if (partial_path[2]) { // If there is more after the "->", then search deeper PrivateAutoComplete (frame, partial_path.substr(2), prefix_path + "->", pointee_type.GetCanonicalType(), matches, word_complete); } else { // Nothing after the "->", so list all members PrivateAutoCompleteMembers (frame, std::string(), std::string(), prefix_path + "->", pointee_type.GetCanonicalType(), matches, word_complete); } } break; default: break; } } break; case '.': if (compiler_type.IsValid()) { switch (type_class) { case lldb::eTypeClassUnion: case lldb::eTypeClassStruct: case lldb::eTypeClassClass: if (partial_path[1]) { // If there is more after the ".", then search deeper PrivateAutoComplete (frame, partial_path.substr(1), prefix_path + ".", compiler_type, matches, word_complete); } else { // Nothing after the ".", so list all members PrivateAutoCompleteMembers (frame, std::string(), partial_path, prefix_path + ".", compiler_type, matches, word_complete); } break; default: break; } } break; default: if (isalpha(ch) || ch == '_' || ch == '$') { const size_t partial_path_len = partial_path.size(); size_t pos = 1; while (pos < partial_path_len) { const char curr_ch = partial_path[pos]; if (isalnum(curr_ch) || curr_ch == '_' || curr_ch == '$') { ++pos; continue; } break; } std::string token(partial_path, 0, pos); remaining_partial_path = partial_path.substr(pos); if (compiler_type.IsValid()) { PrivateAutoCompleteMembers (frame, token, remaining_partial_path, prefix_path, compiler_type, matches, word_complete); } else if (frame) { // We haven't found our variable yet const bool get_file_globals = true; VariableList *variable_list = frame->GetVariableList(get_file_globals); if (!variable_list) break; const size_t num_variables = variable_list->GetSize(); for (size_t i=0; i<num_variables; ++i) { Variable *variable = variable_list->GetVariableAtIndex(i).get(); if (!variable) continue; const char *variable_name = variable->GetName().AsCString(); if (strstr(variable_name, token.c_str()) == variable_name) { if (strcmp (variable_name, token.c_str()) == 0) { Type *variable_type = variable->GetType(); if (variable_type) { CompilerType variable_compiler_type (variable_type->GetForwardCompilerType ()); PrivateAutoComplete (frame, remaining_partial_path, prefix_path + token, // Anything that has been resolved already will be in here variable_compiler_type.GetCanonicalType(), matches, word_complete); } else { matches.AppendString (prefix_path + variable_name); } } else if (remaining_partial_path.empty()) { matches.AppendString (prefix_path + variable_name); } } } } } break; } } }
CompilerType GoASTContext::GetChildCompilerTypeAtIndex(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, bool omit_empty_base_classes, bool ignore_array_bounds, std::string &child_name, uint32_t &child_byte_size, int32_t &child_byte_offset, uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, bool &child_is_base_class, bool &child_is_deref_of_parent, ValueObject *valobj, uint64_t &language_flags) { child_name.clear(); child_byte_size = 0; child_byte_offset = 0; child_bitfield_bit_size = 0; child_bitfield_bit_offset = 0; child_is_base_class = false; child_is_deref_of_parent = false; language_flags = 0; if (!type || !GetCompleteType(type)) return CompilerType(); GoType *t = static_cast<GoType *>(type); if (t->GetStruct()) { uint64_t bit_offset; CompilerType ret = GetFieldAtIndex(type, idx, child_name, &bit_offset, nullptr, nullptr); child_byte_size = ret.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); child_byte_offset = bit_offset / 8; return ret; } else if (t->GetGoKind() == GoType::KIND_PTR) { CompilerType pointee = t->GetElementType(); if (!pointee.IsValid() || pointee.IsVoidType()) return CompilerType(); if (transparent_pointers && pointee.IsAggregateType()) { bool tmp_child_is_deref_of_parent = false; return pointee.GetChildCompilerTypeAtIndex(exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, tmp_child_is_deref_of_parent, valobj, language_flags); } else { child_is_deref_of_parent = true; const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; if (parent_name) { child_name.assign(1, '*'); child_name += parent_name; } // We have a pointer to an simple type if (idx == 0 && pointee.GetCompleteType()) { child_byte_size = pointee.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); child_byte_offset = 0; return pointee; } } } else if (GoArray *a = t->GetArray()) { if (ignore_array_bounds || idx < a->GetLength()) { CompilerType element_type = a->GetElementType(); if (element_type.GetCompleteType()) { char element_name[64]; ::snprintf(element_name, sizeof(element_name), "[%zu]", idx); child_name.assign(element_name); child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; return element_type; } } } else if (t->IsTypedef()) { return t->GetElementType().GetChildCompilerTypeAtIndex( exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, valobj, language_flags); } return CompilerType(); }
void FormatManager::GetPossibleMatches( ValueObject &valobj, CompilerType compiler_type, uint32_t reason, lldb::DynamicValueType use_dynamic, FormattersMatchVector &entries, bool did_strip_ptr, bool did_strip_ref, bool did_strip_typedef, bool root_level) { compiler_type = compiler_type.GetTypeForFormatters(); ConstString type_name(compiler_type.GetConstTypeName()); if (valobj.GetBitfieldBitSize() > 0) { StreamString sstring; sstring.Printf("%s:%d", type_name.AsCString(), valobj.GetBitfieldBitSize()); ConstString bitfieldname(sstring.GetString()); entries.push_back( {bitfieldname, 0, did_strip_ptr, did_strip_ref, did_strip_typedef}); reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField; } if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) { entries.push_back( {type_name, reason, did_strip_ptr, did_strip_ref, did_strip_typedef}); ConstString display_type_name(compiler_type.GetDisplayTypeName()); if (display_type_name != type_name) entries.push_back({display_type_name, reason, did_strip_ptr, did_strip_ref, did_strip_typedef}); } for (bool is_rvalue_ref = true, j = true; j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) { CompilerType non_ref_type = compiler_type.GetNonReferenceType(); GetPossibleMatches( valobj, non_ref_type, reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference, use_dynamic, entries, did_strip_ptr, true, did_strip_typedef); if (non_ref_type.IsTypedefType()) { CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType(); deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType(); GetPossibleMatches( valobj, deffed_referenced_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, use_dynamic, entries, did_strip_ptr, did_strip_ref, true); // this is not exactly the usual meaning of stripping typedefs } } if (compiler_type.IsPointerType()) { CompilerType non_ptr_type = compiler_type.GetPointeeType(); GetPossibleMatches( valobj, non_ptr_type, reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference, use_dynamic, entries, true, did_strip_ref, did_strip_typedef); if (non_ptr_type.IsTypedefType()) { CompilerType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType(); GetPossibleMatches( valobj, deffed_pointed_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, use_dynamic, entries, did_strip_ptr, did_strip_ref, true); // this is not exactly the usual meaning of stripping typedefs } } for (lldb::LanguageType language_type : GetCandidateLanguages(valobj)) { if (Language *language = Language::FindPlugin(language_type)) { for (ConstString candidate : language->GetPossibleFormattersMatches(valobj, use_dynamic)) { entries.push_back( {candidate, reason | lldb_private::eFormatterChoiceCriterionLanguagePlugin, did_strip_ptr, did_strip_ref, did_strip_typedef}); } } } // try to strip typedef chains if (compiler_type.IsTypedefType()) { CompilerType deffed_type = compiler_type.GetTypedefedType(); GetPossibleMatches( valobj, deffed_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, use_dynamic, entries, did_strip_ptr, did_strip_ref, true); } if (root_level) { do { if (!compiler_type.IsValid()) break; CompilerType unqual_compiler_ast_type = compiler_type.GetFullyUnqualifiedType(); if (!unqual_compiler_ast_type.IsValid()) break; if (unqual_compiler_ast_type.GetOpaqueQualType() != compiler_type.GetOpaqueQualType()) GetPossibleMatches(valobj, unqual_compiler_ast_type, reason, use_dynamic, entries, did_strip_ptr, did_strip_ref, did_strip_typedef); } while (false); // if all else fails, go to static type if (valobj.IsDynamic()) { lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue()); if (static_value_sp) GetPossibleMatches( *static_value_sp.get(), static_value_sp->GetCompilerType(), reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue, use_dynamic, entries, did_strip_ptr, did_strip_ref, did_strip_typedef, true); } } }