PyType PyType::target() const { const std::string &typeName = name(); if (isPointerType(typeName) || isArrayType(typeName)) return lookupType(targetName(), m_module); return PyType(); }
PyType PyType::lookupType(const std::string &typeNameIn, ULONG64 module) { if (debuggingTypeEnabled()) DebugPrint() << "lookup type '" << typeNameIn << "'"; std::string typeName = typeNameIn; trimBack(typeName); trimFront(typeName); if (isPointerType(typeName) || isArrayType(typeName)) return PyType(0, 0, typeName); if (typeName.find("enum ") == 0) typeName.erase(0, 5); if (endsWith(typeName, " const")) typeName.erase(typeName.length() - 6); if (typeName == "__int64" || typeName == "unsigned __int64") typeName.erase(typeName.find("__"), 2); const static std::regex typeNameRE("^[a-zA-Z_][a-zA-Z0-9_]*!?[a-zA-Z0-9_<>:, \\*\\&\\[\\]]*$"); if (!std::regex_match(typeName, typeNameRE)) return PyType(); CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols(); ULONG typeId; HRESULT result = S_FALSE; if (module != 0 && !isIntegralType(typeName) && !isFloatType(typeName)) result = symbols->GetTypeId(module, typeName.c_str(), &typeId); if (FAILED(result) || result == S_FALSE) result = symbols->GetSymbolTypeId(typeName.c_str(), &typeId, &module); if (FAILED(result)) return createUnresolvedType(typeName); return PyType(module, typeId, typeName); }
// Create a new storage instance. Chimera::Storage::Storage(const Chimera *ct) : _parsed_type(ct), _ptr_storage(0), _tmp_state(0), _valid(true) { if (!isPointerType()) { // Create a default fundamental or value type. _value_storage = QVariant(_parsed_type->metatype(), (const void *)0); } }
QByteArray gdbQuoteTypes(const QByteArray &type) { // gdb does not understand sizeof(Core::IDocument*). // "sizeof('Core::IDocument*')" is also not acceptable, // it needs to be "sizeof('Core::IDocument'*)" // // We never will have a perfect solution here (even if we had a full blown // C++ parser as we do not have information on what is a type and what is // a variable name. So "a<b>::c" could either be two comparisons of values // 'a', 'b' and '::c', or a nested type 'c' in a template 'a<b>'. We // assume here it is the latter. //return type; // (*('myns::QPointer<myns::QObject>*'*)0x684060)" is not acceptable // (*('myns::QPointer<myns::QObject>'**)0x684060)" is acceptable if (isPointerType(type)) return gdbQuoteTypes(stripPointerType(type)) + '*'; QByteArray accu; QByteArray result; int templateLevel = 0; const char colon = ':'; const char singleQuote = '\''; const char lessThan = '<'; const char greaterThan = '>'; for (int i = 0; i != type.size(); ++i) { const char c = type.at(i); if (isLetterOrNumber(c) || c == '_' || c == colon || c == ' ') { accu += c; } else if (c == lessThan) { ++templateLevel; accu += c; } else if (c == greaterThan) { --templateLevel; accu += c; } else if (templateLevel > 0) { accu += c; } else { if (accu.contains(colon) || accu.contains(lessThan)) result += singleQuote + accu + singleQuote; else result += accu; accu.clear(); result += c; } } if (accu.contains(colon) || accu.contains(lessThan)) result += singleQuote + accu + singleQuote; else result += accu; //qDebug() << "GDB_QUOTING" << type << " TO " << result; return result; }
static GuessChildrenResult guessChildren(const QByteArray &type) { if (isIntOrFloatType(type)) return HasNoChildren; if (isCharPointerType(type)) return HasNoChildren; if (isPointerType(type)) return HasChildren; if (type.endsWith("QString")) return HasNoChildren; return HasPossiblyChildren; }
TCResult ast::SliceOp::typecheck(sst::TypecheckState* fs, fir::Type* inferred) { fs->pushLoc(this); defer(fs->popLoc()); fs->pushAnonymousTree(); defer(fs->popTree()); auto array = this->expr->typecheck(fs).expr(); auto ty = array->type; fs->enterSubscript(array); defer(fs->leaveSubscript()); fir::Type* elm = 0; if(ty->isDynamicArrayType() || ty->isArraySliceType() || ty->isArrayType()) elm = ty->getArrayElementType(); else if(ty->isStringType()) elm = fir::Type::getInt8(); else if(ty->isPointerType()) elm = ty->getPointerElementType(); else error(array, "invalid type '%s' for slice operation", ty); auto begin = this->start ? this->start->typecheck(fs, fir::Type::getInt64()).expr() : 0; auto end = this->end ? this->end->typecheck(fs, fir::Type::getInt64()).expr() : 0; if(begin && !begin->type->isIntegerType()) error(begin, "expected integer type for start index of slice; found '%s'", begin->type); if(end && !end->type->isIntegerType()) error(end, "expected integer type for end index of slice; found '%s'", end->type); //* how it goes: // 1. strings and dynamic arrays are always sliced mutably. // 2. slices of slices naturally inherit their mutability. // 3. arrays are sliced immutably. // 4. pointers inherit their mutability as well. bool ismut = sst::getMutabilityOfSliceOfType(ty); auto ret = util::pool<sst::SliceOp>(this->loc, fir::ArraySliceType::get(elm, ismut)); ret->expr = array; ret->begin = begin; ret->end = end; return TCResult(ret); }
// Return the address of the storage. void *Chimera::Storage::address() { if (isPointerType()) { if (_parsed_type->name().endsWith('*')) return &_ptr_storage; return _ptr_storage; } if (_parsed_type->typeDef() == sipType_QVariant) return &_value_storage; return _value_storage.data(); }
std::string PyType::targetName() const { const std::string &typeName = name(); if (isPointerType(typeName)) return stripPointerType(typeName); if (isArrayType(typeName)) { const auto openArrayPos = typeName.find_first_of('['); if (openArrayPos == std::string::npos) return typeName; const auto closeArrayPos = typeName.find_first_of(']', openArrayPos); if (closeArrayPos == std::string::npos) return typeName; return typeName.substr(0, openArrayPos) + typeName.substr(closeArrayPos + 1); } return typeName; }
int PyType::code() const { if (!m_resolved) return TypeCodeUnresolvable; if (m_tag < 0) { // try to parse typeName const std::string &typeName = name(); if (typeName.empty()) return TypeCodeUnresolvable; if (isPointerType(typeName)) return TypeCodePointer; if (isArrayType(typeName)) return TypeCodeArray; if (typeName.find("<function>") == 0) return TypeCodeFunction; if (isIntegralType(typeName)) return TypeCodeIntegral; if (isFloatType(typeName)) return TypeCodeFloat; IDebugSymbolGroup2 *sg = 0; if (FAILED(ExtensionCommandContext::instance()->symbols()->CreateSymbolGroup2(&sg))) return TypeCodeStruct; if (knownType(name(), 0) != KT_Unknown) return TypeCodeStruct; const std::string helperValueName = SymbolGroupValue::pointedToSymbolName(0, name(true)); ULONG index = DEBUG_ANY_ID; if (SUCCEEDED(sg->AddSymbol(helperValueName.c_str(), &index))) m_tag = PyValue(index, sg).tag(); sg->Release(); } switch (m_tag) { case SymTagUDT: return TypeCodeStruct; case SymTagEnum: return TypeCodeEnum; case SymTagTypedef: return TypeCodeTypedef; case SymTagFunctionType: return TypeCodeFunction; case SymTagPointerType: return TypeCodePointer; case SymTagArrayType: return TypeCodeArray; case SymTagBaseType: return isIntegralType(name()) ? TypeCodeIntegral : TypeCodeFloat; default: break; } return TypeCodeStruct; }
PyFields PyType::fields() const { CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols(); PyFields fields; if (isArrayType(name()) || isPointerType(name())) return fields; for (ULONG fieldIndex = 0;; ++fieldIndex) { ULONG size = 0; symbols->GetFieldName(m_module, m_typeId, fieldIndex, NULL, 0, &size); if (size == 0) break; std::string name(size - 1, '\0'); if (FAILED(symbols->GetFieldName(m_module, m_typeId, fieldIndex, &name[0], size, NULL))) break; fields.push_back(PyField(name, *this)); } return fields; }
// Convert the stored value to a Python object. PyObject *Chimera::Storage::toPyObject() const { // Pointer-class and mapped types are not stored in the QVariant. if (isPointerType()) { if (!_ptr_storage) { Py_INCREF(Py_None); return Py_None; } return sipConvertFromType(_ptr_storage, _parsed_type->typeDef(), 0); } if (_parsed_type->typeDef() == sipType_QVariant) return Chimera::toAnyPyObject(_value_storage); return _parsed_type->toPyObject(_value_storage); }
// Create a new storage instance containing a converted Python object. Chimera::Storage::Storage(const Chimera *ct, PyObject *py) : _parsed_type(ct), _ptr_storage(0), _tmp_state(0) { // We convert to a QVariant even for pointer types because this has the // side-effect of ensuring the object doesn't get garbage collected. _valid = _parsed_type->fromPyObject(py, &_value_storage); if (isPointerType()) { int is_err = 0; _ptr_storage = sipForceConvertToType(py, _parsed_type->typeDef(), 0, 0, &_tmp_state, &is_err); if (is_err) { _value_storage = QVariant(); _valid = false; } } }
void WatchData::setValue(const QString &value0) { value = value0; if (value == "{...}") { value.clear(); hasChildren = true; // at least one... } // strip off quoted characters for chars. if (value.endsWith(QLatin1Char('\'')) && type.endsWith("char")) { const int blankPos = value.indexOf(QLatin1Char(' ')); if (blankPos != -1) value.truncate(blankPos); } // avoid duplicated information if (value.startsWith(QLatin1Char('(')) && value.contains(") 0x")) value = value.mid(value.lastIndexOf(") 0x") + 2); // doubles are sometimes displayed as "@0x6141378: 1.2". // I don't want that. if (/*isIntOrFloatType(type) && */ value.startsWith("@0x") && value.contains(':')) { value = value.mid(value.indexOf(':') + 2); setHasChildren(false); } // "numchild" is sometimes lying //MODEL_DEBUG("\n\n\nPOINTER: " << type << value); if (isPointerType(type)) setHasChildren(value != "0x0" && value != "<null>" && !isCharPointerType(type)); // pointer type information is available in the 'type' // column. No need to duplicate it here. if (value.startsWith(QLatin1Char('(') + type + ") 0x")) value = value.section(QLatin1Char(' '), -1, -1); setValueUnneeded(); }