================ @@ -402,4 +404,122 @@ Interpreter::Visit(const BitFieldExtractionNode *node) { return child_valobj_sp; } +static lldb::TypeSystemSP GetTypeSystemFromCU(std::shared_ptr<StackFrame> ctx) { + SymbolContext symbol_context = + ctx->GetSymbolContext(lldb::eSymbolContextCompUnit); + lldb::LanguageType language = symbol_context.comp_unit->GetLanguage(); + + symbol_context = ctx->GetSymbolContext(lldb::eSymbolContextModule); + llvm::Expected<lldb::TypeSystemSP> type_system = + symbol_context.module_sp->GetTypeSystemForLanguage(language); + + if (type_system) + return *type_system; + + return lldb::TypeSystemSP(); +} + +static CompilerType GetBasicType(lldb::TypeSystemSP type_system, + lldb::BasicType basic_type) { + if (type_system) + if (auto compiler_type = type_system.get()->GetBasicTypeFromAST(basic_type)) + return compiler_type; + + CompilerType empty_type; + return empty_type; +} + +llvm::Expected<CompilerType> +Interpreter::PickIntegerType(lldb::TypeSystemSP type_system, + std::shared_ptr<ExecutionContextScope> ctx, + const IntegerLiteralNode *literal) { + // Binary, Octal, Hexadecimal and literals with a U suffix are allowed to be + // an unsigned integer. + bool unsigned_is_allowed = literal->IsUnsigned() || literal->GetRadix() != 10; + + // Try int/unsigned int. + uint64_t int_byte_size = 0; + if (auto temp = + GetBasicType(type_system, lldb::eBasicTypeInt).GetByteSize(ctx.get())) + int_byte_size = *temp; + unsigned int_size = int_byte_size * CHAR_BIT; + llvm::APInt apint = literal->GetValue(); + if (!literal->IsLong() && !literal->IsLongLong() && apint.isIntN(int_size)) { + if (!literal->IsUnsigned() && apint.isIntN(int_size - 1)) + return GetBasicType(type_system, lldb::eBasicTypeInt); + if (unsigned_is_allowed) + return GetBasicType(type_system, lldb::eBasicTypeUnsignedInt); + } + // Try long/unsigned long. + uint64_t long_byte_size = 0; + if (auto temp = GetBasicType(type_system, lldb::eBasicTypeLong) + .GetByteSize(ctx.get())) + long_byte_size = *temp; + unsigned long_size = long_byte_size * CHAR_BIT; + if (!literal->IsLongLong() && apint.isIntN(long_size)) { + if (!literal->IsUnsigned() && apint.isIntN(long_size - 1)) + return GetBasicType(type_system, lldb::eBasicTypeLong); + if (unsigned_is_allowed) + return GetBasicType(type_system, lldb::eBasicTypeUnsignedLong); + } + // Try long long/unsigned long long. + uint64_t long_long_byte_size = 0; + if (auto temp = GetBasicType(type_system, lldb::eBasicTypeLongLong) + .GetByteSize(ctx.get())) + long_long_byte_size = *temp; + unsigned long_long_size = long_long_byte_size * CHAR_BIT; + if (apint.isIntN(long_long_size)) { + if (!literal->IsUnsigned() && apint.isIntN(long_long_size - 1)) + return GetBasicType(type_system, lldb::eBasicTypeLongLong); + // If we still couldn't decide a type, we probably have something that + // does not fit in a signed long long, but has no U suffix. Also known as: + // + // warning: integer literal is too large to be represented in a signed + // integer type, interpreting as unsigned [-Wimplicitly-unsigned-literal] + // + return GetBasicType(type_system, lldb::eBasicTypeUnsignedLongLong); ---------------- labath wrote:
I'm afraid I don't see the difference, and I've spent a lot of time looking at this function. Here's my attempt at an equivalent version. I think it should be equivalent, but if it's not, then maybe that means we should make the differences more prominent. ``` SmallVector<std::pair<BasicType, BasicType>, 3> candidates; if (literal->GetTypeSuffix() <= IntegerTypeSuffix::None) candidates.emplace_back(eBasicTypeInt, unsigned_is_allowed ? eBasicTypeUInt : eBasicTypeInvalid); if (literal->GetTypeSuffix() <= IntegerTypeSuffix::Long) candidates.emplace_back(eBasicTypeLong, unsigned_is_allowed ? eBasicTypeULong : eBasicTypeInvalid); candidates.emplace_back(eBasicTypeLongLong, eBasicTypeULLong); for (auto [signed_, unsigned_] : candidates) { CompilerType signed_type = type_system->GetBasicTypeFromAST(signed_); if (!signed_type) continue; llvm::Expected<uint64_t> size = signed_type.GetBitSize(ctx.get()); if (!size) return size.takeError(); if (!literal.IsUnsigned() && apint.isIntN(*size-1)) return signed_type; if (unsigned_ != eBasicTypeInvalid && apint.isIntN(*size)) return type_system->GetBasicTypeFromAST(unsigned_) } return llvm::make_error(...); ``` A small difference is that this continues if it can't find (e.g.) the int type. I think this is fine -- if somehow we do end up with a type system that does not have an int type, then it makes sense to try the next larger one. https://github.com/llvm/llvm-project/pull/152308 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits