================
@@ -127,6 +127,151 @@ Interpreter::UnaryConversion(lldb::ValueObjectSP valobj,
uint32_t location) {
return valobj;
}
+/// Basic types with a lower rank are converted to the basic type
+/// with a higher rank.
+static size_t ConversionRank(CompilerType type) {
+ switch (type.GetCanonicalType().GetBasicTypeEnumeration()) {
+ case lldb::eBasicTypeBool:
+ return 1;
+ case lldb::eBasicTypeChar:
+ case lldb::eBasicTypeSignedChar:
+ case lldb::eBasicTypeUnsignedChar:
+ return 2;
+ case lldb::eBasicTypeShort:
+ case lldb::eBasicTypeUnsignedShort:
+ return 3;
+ case lldb::eBasicTypeInt:
+ case lldb::eBasicTypeUnsignedInt:
+ return 4;
+ case lldb::eBasicTypeLong:
+ case lldb::eBasicTypeUnsignedLong:
+ return 5;
+ case lldb::eBasicTypeLongLong:
+ case lldb::eBasicTypeUnsignedLongLong:
+ return 6;
+ case lldb::eBasicTypeInt128:
+ case lldb::eBasicTypeUnsignedInt128:
+ return 7;
+ case lldb::eBasicTypeHalf:
+ return 8;
+ case lldb::eBasicTypeFloat:
+ return 9;
+ case lldb::eBasicTypeDouble:
+ return 10;
+ case lldb::eBasicTypeLongDouble:
+ return 11;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static lldb::BasicType BasicTypeToUnsigned(lldb::BasicType basic_type) {
+ switch (basic_type) {
+ case lldb::eBasicTypeChar:
+ case lldb::eBasicTypeSignedChar:
+ return lldb::eBasicTypeUnsignedChar;
+ case lldb::eBasicTypeShort:
+ return lldb::eBasicTypeUnsignedShort;
+ case lldb::eBasicTypeInt:
+ return lldb::eBasicTypeUnsignedInt;
+ case lldb::eBasicTypeLong:
+ return lldb::eBasicTypeUnsignedLong;
+ case lldb::eBasicTypeLongLong:
+ return lldb::eBasicTypeUnsignedLongLong;
+ case lldb::eBasicTypeInt128:
+ return lldb::eBasicTypeUnsignedInt128;
+ default:
+ return basic_type;
+ }
+}
+
+llvm::Expected<CompilerType>
+Interpreter::PromoteSignedInteger(CompilerType &lhs_type,
+ CompilerType &rhs_type) {
+ // This expects that Rank(lhs_type) < Rank(rhs_type).
+ if (!lhs_type.IsSigned() && rhs_type.IsSigned()) {
+ llvm::Expected<uint64_t> lhs_size =
+ lhs_type.GetBitSize(m_exe_ctx_scope.get());
+ if (!lhs_size)
+ return lhs_size.takeError();
+ llvm::Expected<uint64_t> rhs_size =
+ rhs_type.GetBitSize(m_exe_ctx_scope.get());
+ if (!rhs_size)
+ return rhs_size.takeError();
+
+ if (*rhs_size == *lhs_size) {
+ llvm::Expected<lldb::TypeSystemSP> type_system =
+ GetTypeSystemFromCU(m_exe_ctx_scope);
+ if (!type_system)
+ return type_system.takeError();
+ CompilerType r_type_unsigned = GetBasicType(
+ *type_system,
+ BasicTypeToUnsigned(
+ rhs_type.GetCanonicalType().GetBasicTypeEnumeration()));
+ return r_type_unsigned;
+ }
+ }
+ return rhs_type;
+}
+
+llvm::Expected<CompilerType>
+Interpreter::ArithmeticConversion(lldb::ValueObjectSP &lhs,
+ lldb::ValueObjectSP &rhs, uint32_t location)
{
+ // Apply unary conversion for both operands.
+ auto lhs_or_err = UnaryConversion(lhs, location);
+ if (!lhs_or_err)
+ return lhs_or_err.takeError();
+ lhs = *lhs_or_err;
+ auto rhs_or_err = UnaryConversion(rhs, location);
+ if (!rhs_or_err)
+ return rhs_or_err.takeError();
+ rhs = *rhs_or_err;
+
+ CompilerType lhs_type = lhs->GetCompilerType();
+ CompilerType rhs_type = rhs->GetCompilerType();
+
+ // If types already match, no need for further conversions.
+ if (lhs_type.CompareTypes(rhs_type))
+ return lhs_type;
+
+ // If either of the operands is not arithmetic (e.g. pointer), we're done.
+ if (!lhs_type.IsScalarType() || !rhs_type.IsScalarType())
+ return CompilerType();
+
+ size_t l_rank = ConversionRank(lhs_type);
+ size_t r_rank = ConversionRank(rhs_type);
+ if (l_rank == 0 || r_rank == 0)
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, "unexpected basic type in arithmetic operation", location);
+
+ // If both operands are integer, check if we need to promote
+ // the higher ranked signed type.
+ if (lhs_type.IsInteger() && rhs_type.IsInteger()) {
+ using Rank = std::tuple<size_t, bool>;
+ Rank int_l_rank = {l_rank, !lhs_type.IsSigned()};
+ Rank int_r_rank = {r_rank, !rhs_type.IsSigned()};
+ if (int_l_rank < int_r_rank) {
+ auto type_or_err = PromoteSignedInteger(lhs_type, rhs_type);
+ if (!type_or_err)
+ return type_or_err.takeError();
+ return *type_or_err;
+ }
+ if (int_l_rank > int_r_rank) {
+ auto type_or_err = PromoteSignedInteger(rhs_type, lhs_type);
+ if (!type_or_err)
+ return type_or_err.takeError();
+ return *type_or_err;
+ }
+ return lhs_type;
+ }
+
+ // Handle other combinations of integer and floating point operands.
+ if (l_rank < r_rank)
+ return rhs_type;
----------------
kuilpd wrote:
Doesn't `-Wnarrowing` only trigger when list initialization is involved? This
is the code specifically for arithmetic conversion, I don't think C++ warns
about any combination of scalar argument types in binary math. We can write
`char c = double_var + int_var` and it will be fine. Or am I misunderstanding
the issue?
https://github.com/llvm/llvm-project/pull/177208
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits