================
@@ -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

Reply via email to