diff --git a/lldb/docs/dil-expr-lang.ebnf b/lldb/docs/dil-expr-lang.ebnf index 67328939ba420..20804935bf356 100644 --- a/lldb/docs/dil-expr-lang.ebnf +++ b/lldb/docs/dil-expr-lang.ebnf @@ -8,7 +8,7 @@ expression = unary_expression ; unary_expression = postfix_expression | unary_operator expression ; -unary_operator = "*" | "&" ; +unary_operator = "*" | "&" | "+" | "-"; postfix_expression = primary_expression | postfix_expression "[" integer_literal "]" diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index 16a2e0b5a52fb..b45d33bc3ac64 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -412,6 +412,18 @@ class TypeSystem : public PluginInterface, GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, bool expand_pack); + // DIL + + /// Checks if the type is eligible for integral promotion. + virtual bool IsPromotableIntegerType(lldb::opaque_compiler_type_t type); + + /// Perform integral promotion on a given type. + /// This promotes eligible types (boolean, integers, unscoped enumerations) + /// to a larger integer type according to type system rules. + /// \returns Promoted type. + virtual llvm::Expected + DoIntegralPromotion(CompilerType from, ExecutionContextScope *exe_scope); + // Dumping types #ifndef NDEBUG diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h index 1d10755c46e39..900eb8a792a1e 100644 --- a/lldb/include/lldb/ValueObject/DILAST.h +++ b/lldb/include/lldb/ValueObject/DILAST.h @@ -32,6 +32,8 @@ enum class NodeKind { enum class UnaryOpKind { AddrOf, // "&" Deref, // "*" + Minus, // "-" + Plus, // "+" }; /// Forward declaration, for use in DIL AST nodes. Definition is at the very diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h index 5a48c2c989f4d..11f44336cbf55 100644 --- a/lldb/include/lldb/ValueObject/DILEval.h +++ b/lldb/include/lldb/ValueObject/DILEval.h @@ -59,6 +59,8 @@ class Interpreter : Visitor { llvm::Expected Visit(const FloatLiteralNode *node) override; + llvm::Expected + UnaryConversion(lldb::ValueObjectSP valobj); llvm::Expected PickIntegerType(lldb::TypeSystemSP type_system, std::shared_ptr ctx, diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 39aacdb58e694..4d4ca522e052a 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -7320,6 +7320,102 @@ CompilerType TypeSystemClang::GetTypeForFormatters(void *type) { return CompilerType(); } +bool TypeSystemClang::IsPromotableIntegerType( + lldb::opaque_compiler_type_t type) { + // Unscoped enums are always considered as promotable, even if their + // underlying type does not need to be promoted (e.g. "int"). + bool is_signed = false; + bool isUnscopedEnumerationType = + IsEnumerationType(type, is_signed) && !IsScopedEnumerationType(type); + if (isUnscopedEnumerationType) + return true; + + switch (GetBasicTypeEnumeration(type)) { + case lldb::eBasicTypeBool: + case lldb::eBasicTypeChar: + case lldb::eBasicTypeSignedChar: + case lldb::eBasicTypeUnsignedChar: + case lldb::eBasicTypeShort: + case lldb::eBasicTypeUnsignedShort: + case lldb::eBasicTypeWChar: + case lldb::eBasicTypeSignedWChar: + case lldb::eBasicTypeUnsignedWChar: + case lldb::eBasicTypeChar16: + case lldb::eBasicTypeChar32: + return true; + + default: + return false; + } + + llvm_unreachable("All cases handled above."); +} + +llvm::Expected +TypeSystemClang::DoIntegralPromotion(CompilerType from, + ExecutionContextScope *exe_scope) { + if (!from.IsInteger() && !from.IsUnscopedEnumerationType()) + return from; + + if (!from.IsPromotableIntegerType()) + return from; + + if (from.IsUnscopedEnumerationType()) { + EnumDecl *enum_decl = GetAsEnumDecl(from); + CompilerType promotion_type = GetType(enum_decl->getPromotionType()); + return DoIntegralPromotion(promotion_type, exe_scope); + } + + lldb::BasicType builtin_type = + from.GetCanonicalType().GetBasicTypeEnumeration(); + uint64_t from_size = 0; + if (builtin_type == lldb::eBasicTypeWChar || + builtin_type == lldb::eBasicTypeSignedWChar || + builtin_type == lldb::eBasicTypeUnsignedWChar || + builtin_type == lldb::eBasicTypeChar16 || + builtin_type == lldb::eBasicTypeChar32) { + // Find the type that can hold the entire range of values for our type. + bool is_signed = from.IsSigned(); + llvm::Expected from_size = from.GetByteSize(exe_scope); + if (!from_size) + return from_size.takeError(); + CompilerType promote_types[] = { + GetBasicTypeFromAST(lldb::eBasicTypeInt), + GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt), + GetBasicTypeFromAST(lldb::eBasicTypeLong), + GetBasicTypeFromAST(lldb::eBasicTypeUnsignedLong), + GetBasicTypeFromAST(lldb::eBasicTypeLongLong), + GetBasicTypeFromAST(lldb::eBasicTypeUnsignedLongLong), + }; + for (CompilerType &type : promote_types) { + llvm::Expected byte_size = type.GetByteSize(exe_scope); + if (!byte_size) + return byte_size.takeError(); + if (*from_size < *byte_size || + (*from_size == *byte_size && is_signed == type.IsSigned())) { + return type; + } + } + llvm_unreachable("char type should fit into long long"); + } + + // Here we can promote only to "int" or "unsigned int". + CompilerType int_type = GetBasicTypeFromAST(lldb::eBasicTypeInt); + llvm::Expected int_byte_size = int_type.GetByteSize(exe_scope); + if (!int_byte_size) + return int_byte_size.takeError(); + + // Signed integer types can be safely promoted to "int". + if (from.IsSigned()) { + return int_type; + } + // Unsigned integer types are promoted to "unsigned int" if "int" cannot hold + // their entire value range. + return (from_size == *int_byte_size) + ? GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt) + : int_type; +} + clang::EnumDecl *TypeSystemClang::GetAsEnumDecl(const CompilerType &type) { const clang::EnumType *enutype = llvm::dyn_cast(ClangUtil::GetCanonicalQualType(type)); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 709f89590ba3b..0ca1a1e2578b3 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -939,6 +939,14 @@ class TypeSystemClang : public TypeSystem { CompilerType GetTypeForFormatters(void *type) override; + // DIL + + bool IsPromotableIntegerType(lldb::opaque_compiler_type_t type) override; + + llvm::Expected + DoIntegralPromotion(CompilerType from, + ExecutionContextScope *exe_scope) override; + #define LLDB_INVALID_DECL_LEVEL UINT32_MAX // LLDB_INVALID_DECL_LEVEL is returned by CountDeclLevels if child_decl_ctx // could not be found in decl_ctx. diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index 62c0ddf51c012..a22e817f818ce 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -373,30 +373,10 @@ bool CompilerType::IsScalarOrUnscopedEnumerationType() const { } bool CompilerType::IsPromotableIntegerType() const { - // Unscoped enums are always considered as promotable, even if their - // underlying type does not need to be promoted (e.g. "int"). - if (IsUnscopedEnumerationType()) - return true; - - switch (GetBasicTypeEnumeration()) { - case lldb::eBasicTypeBool: - case lldb::eBasicTypeChar: - case lldb::eBasicTypeSignedChar: - case lldb::eBasicTypeUnsignedChar: - case lldb::eBasicTypeShort: - case lldb::eBasicTypeUnsignedShort: - case lldb::eBasicTypeWChar: - case lldb::eBasicTypeSignedWChar: - case lldb::eBasicTypeUnsignedWChar: - case lldb::eBasicTypeChar16: - case lldb::eBasicTypeChar32: - return true; - - default: - return false; - } - - llvm_unreachable("All cases handled above."); + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsPromotableIntegerType(m_type); + return false; } bool CompilerType::IsPointerToVoid() const { diff --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp index f7d634ffa2dec..7df049084e6fb 100644 --- a/lldb/source/Symbol/TypeSystem.cpp +++ b/lldb/source/Symbol/TypeSystem.cpp @@ -123,6 +123,16 @@ CompilerType TypeSystem::GetTypeForFormatters(void *type) { return CompilerType(weak_from_this(), type); } +bool TypeSystem::IsPromotableIntegerType(lldb::opaque_compiler_type_t type) { + return false; +} + +llvm::Expected +TypeSystem::DoIntegralPromotion(CompilerType from, + ExecutionContextScope *exe_scope) { + return CompilerType(); +} + bool TypeSystem::IsTemplateType(lldb::opaque_compiler_type_t type) { return false; } diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp index c6cf41ee9e9ee..58ab85e522ce4 100644 --- a/lldb/source/ValueObject/DILEval.cpp +++ b/lldb/source/ValueObject/DILEval.cpp @@ -21,6 +21,101 @@ namespace lldb_private::dil { +static llvm::Expected +GetTypeSystemFromCU(std::shared_ptr ctx) { + auto stack_frame = ctx->CalculateStackFrame(); + if (!stack_frame) + return llvm::createStringError("no stack frame in this context"); + SymbolContext symbol_context = + stack_frame->GetSymbolContext(lldb::eSymbolContextCompUnit); + lldb::LanguageType language = symbol_context.comp_unit->GetLanguage(); + + symbol_context = stack_frame->GetSymbolContext(lldb::eSymbolContextModule); + return symbol_context.module_sp->GetTypeSystemForLanguage(language); +} + +static CompilerType GetBasicType(lldb::TypeSystemSP type_system, + lldb::BasicType basic_type) { + if (type_system) + return type_system.get()->GetBasicTypeFromAST(basic_type); + + return CompilerType(); +} + +static lldb::ValueObjectSP +ArrayToPointerConversion(lldb::ValueObjectSP valobj, + std::shared_ptr ctx) { + uint64_t addr = valobj->GetLoadAddress(); + ExecutionContext exe_ctx; + ctx->CalculateExecutionContext(exe_ctx); + return ValueObject::CreateValueObjectFromAddress( + "result", addr, exe_ctx, + valobj->GetCompilerType().GetArrayElementType(ctx.get()).GetPointerType(), + /* do_deref */ false); +} + +llvm::Expected +Interpreter::UnaryConversion(lldb::ValueObjectSP valobj) { + // Perform usual conversions for unary operators. At the moment this includes + // array-to-pointer and the integral promotion for eligible types. + llvm::Expected type_system = + GetTypeSystemFromCU(m_exe_ctx_scope); + if (!type_system) + return type_system.takeError(); + CompilerType in_type = valobj->GetCompilerType(); + CompilerType result_type; + if (valobj->IsBitfield()) { + // Promote bitfields. If `int` can represent the bitfield value, it is + // converted to `int`. Otherwise, if `unsigned int` can represent it, it + // is converted to `unsigned int`. Otherwise, it is treated as its + // underlying type. + uint32_t bitfield_size = valobj->GetBitfieldBitSize(); + // Some bitfields have undefined size (e.g. result of ternary operation). + // The AST's `bitfield_size` of those is 0, and no promotion takes place. + if (bitfield_size > 0 && in_type.IsInteger()) { + CompilerType int_type = GetBasicType(*type_system, lldb::eBasicTypeInt); + CompilerType uint_type = + GetBasicType(*type_system, lldb::eBasicTypeUnsignedInt); + llvm::Expected int_bit_size = + int_type.GetBitSize(m_exe_ctx_scope.get()); + if (!int_bit_size) + return int_bit_size.takeError(); + llvm::Expected uint_bit_size = + uint_type.GetBitSize(m_exe_ctx_scope.get()); + if (!uint_bit_size) + return int_bit_size.takeError(); + if (bitfield_size < *int_bit_size || + (in_type.IsSigned() && bitfield_size == *int_bit_size)) + return valobj->CastToBasicType(int_type); + if (bitfield_size <= *uint_bit_size) + return valobj->CastToBasicType(uint_type); + // Re-create as a const value with the same underlying type + Scalar scalar; + bool resolved = valobj->ResolveValue(scalar); + if (!resolved) + return llvm::createStringError("invalid scalar value"); + return ValueObject::CreateValueObjectFromScalar(m_target, scalar, in_type, + "result"); + } + } + + if (in_type.IsArrayType()) + valobj = ArrayToPointerConversion(valobj, m_exe_ctx_scope); + + if (valobj->GetCompilerType().IsInteger() || + valobj->GetCompilerType().IsUnscopedEnumerationType()) { + llvm::Expected promoted_type = + type_system.get()->DoIntegralPromotion(valobj->GetCompilerType(), + m_exe_ctx_scope.get()); + if (!promoted_type) + return promoted_type.takeError(); + if (!promoted_type->CompareTypes(valobj->GetCompilerType())) + return valobj->CastToBasicType(*promoted_type); + } + + return valobj; +} + static lldb::VariableSP DILFindVariable(ConstString name, VariableList &variable_list) { lldb::VariableSP exact_match; @@ -175,21 +270,21 @@ Interpreter::Visit(const IdentifierNode *node) { llvm::Expected Interpreter::Visit(const UnaryOpNode *node) { Status error; - auto rhs_or_err = Evaluate(node->GetOperand()); - if (!rhs_or_err) - return rhs_or_err; + auto op_or_err = Evaluate(node->GetOperand()); + if (!op_or_err) + return op_or_err; - lldb::ValueObjectSP rhs = *rhs_or_err; + lldb::ValueObjectSP operand = *op_or_err; switch (node->GetKind()) { case UnaryOpKind::Deref: { - lldb::ValueObjectSP dynamic_rhs = rhs->GetDynamicValue(m_use_dynamic); - if (dynamic_rhs) - rhs = dynamic_rhs; + lldb::ValueObjectSP dynamic_op = operand->GetDynamicValue(m_use_dynamic); + if (dynamic_op) + operand = dynamic_op; - lldb::ValueObjectSP child_sp = rhs->Dereference(error); + lldb::ValueObjectSP child_sp = operand->Dereference(error); if (!child_sp && m_use_synthetic) { - if (lldb::ValueObjectSP synth_obj_sp = rhs->GetSyntheticValue()) { + if (lldb::ValueObjectSP synth_obj_sp = operand->GetSyntheticValue()) { error.Clear(); child_sp = synth_obj_sp->Dereference(error); } @@ -202,18 +297,67 @@ Interpreter::Visit(const UnaryOpNode *node) { } case UnaryOpKind::AddrOf: { Status error; - lldb::ValueObjectSP value = rhs->AddressOf(error); + lldb::ValueObjectSP value = operand->AddressOf(error); if (error.Fail()) return llvm::make_error(m_expr, error.AsCString(), node->GetLocation()); return value; } + case UnaryOpKind::Minus: { + if (operand->GetCompilerType().IsReferenceType()) { + operand = operand->Dereference(error); + if (error.Fail()) + return error.ToError(); + } + llvm::Expected conv_op = UnaryConversion(operand); + if (!conv_op) + return conv_op; + operand = *conv_op; + CompilerType operand_type = operand->GetCompilerType(); + if (!operand_type.IsScalarType()) { + std::string errMsg = + llvm::formatv("invalid argument type '{0}' to unary expression", + operand_type.GetTypeName()); + return llvm::make_error(m_expr, errMsg, + node->GetLocation()); + } + Scalar scalar; + bool resolved = operand->ResolveValue(scalar); + if (!resolved) + break; + + bool negated = scalar.UnaryNegate(); + if (negated) + return ValueObject::CreateValueObjectFromScalar( + m_target, scalar, operand->GetCompilerType(), "result"); + break; } - - // Unsupported/invalid operation. - return llvm::make_error( - m_expr, "invalid ast: unexpected binary operator", node->GetLocation()); + case UnaryOpKind::Plus: { + if (operand->GetCompilerType().IsReferenceType()) { + operand = operand->Dereference(error); + if (error.Fail()) + return error.ToError(); + } + llvm::Expected conv_op = UnaryConversion(operand); + if (!conv_op) + return conv_op; + operand = *conv_op; + CompilerType operand_type = operand->GetCompilerType(); + if (!operand_type.IsScalarType() && + // Unary plus is allowed for pointers. + !operand_type.IsPointerType()) { + std::string errMsg = + llvm::formatv("invalid argument type '{0}' to unary expression", + operand_type.GetTypeName()); + return llvm::make_error(m_expr, errMsg, + node->GetLocation()); + } + return operand; + } + } + return llvm::make_error(m_expr, "invalid unary operation", + node->GetLocation()); } llvm::Expected @@ -499,24 +643,6 @@ Interpreter::Visit(const BitFieldExtractionNode *node) { return child_valobj_sp; } -static llvm::Expected -GetTypeSystemFromCU(std::shared_ptr ctx) { - SymbolContext symbol_context = - ctx->GetSymbolContext(lldb::eSymbolContextCompUnit); - lldb::LanguageType language = symbol_context.comp_unit->GetLanguage(); - - symbol_context = ctx->GetSymbolContext(lldb::eSymbolContextModule); - return symbol_context.module_sp->GetTypeSystemForLanguage(language); -} - -static CompilerType GetBasicType(lldb::TypeSystemSP type_system, - lldb::BasicType basic_type) { - if (type_system) - return type_system.get()->GetBasicTypeFromAST(basic_type); - - return CompilerType(); -} - llvm::Expected Interpreter::PickIntegerType(lldb::TypeSystemSP type_system, std::shared_ptr ctx, diff --git a/lldb/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp index 0b2288a9d9230..77879f50cc9ad 100644 --- a/lldb/source/ValueObject/DILLexer.cpp +++ b/lldb/source/ValueObject/DILLexer.cpp @@ -42,7 +42,6 @@ llvm::StringRef Token::GetTokenName(Kind kind) { return "minus"; case Kind::period: return "period"; - return "l_square"; case Kind::plus: return "plus"; case Kind::r_paren: diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp index 8c4f7fdb25bea..b1ba25213c803 100644 --- a/lldb/source/ValueObject/DILParser.cpp +++ b/lldb/source/ValueObject/DILParser.cpp @@ -93,9 +93,12 @@ ASTNodeUP DILParser::ParseExpression() { return ParseUnaryExpression(); } // unary_operator: // "&" // "*" +// "+" +// "-" // ASTNodeUP DILParser::ParseUnaryExpression() { - if (CurToken().IsOneOf({Token::amp, Token::star})) { + if (CurToken().IsOneOf( + {Token::amp, Token::star, Token::minus, Token::plus})) { Token token = CurToken(); uint32_t loc = token.GetLocation(); m_dil_lexer.Advance(); @@ -107,7 +110,12 @@ ASTNodeUP DILParser::ParseUnaryExpression() { case Token::amp: return std::make_unique(loc, UnaryOpKind::AddrOf, std::move(rhs)); - + case Token::minus: + return std::make_unique(loc, UnaryOpKind::Minus, + std::move(rhs)); + case Token::plus: + return std::make_unique(loc, UnaryOpKind::Plus, + std::move(rhs)); default: llvm_unreachable("invalid token kind"); } diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/Makefile b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/Makefile new file mode 100644 index 0000000000000..99998b20bcb05 --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py new file mode 100644 index 0000000000000..53a85fed303f4 --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py @@ -0,0 +1,46 @@ +""" +Test DIL arithmetic. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from lldbsuite.test import lldbutil + + +class TestFrameVarDILArithmetic(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + def test_arithmetic(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp") + ) + + self.runCmd("settings set target.experimental.use-DIL true") + + # Check unary results and integral promotion + self.expect_var_path("+0", value="0") + self.expect_var_path("-0", value="0") + self.expect_var_path("+1", value="1") + self.expect_var_path("-1", value="-1") + self.expect_var_path("-9223372036854775808", value="9223372036854775808") + self.expect_var_path("s", value="10", type="short") + self.expect_var_path("+s", value="10", type="int") + self.expect_var_path("-s", value="-10", type="int") + self.expect_var_path("+us", value="1", type="int") + self.expect_var_path("-us", value="-1", type="int") + self.expect_var_path("+ref", value="2", type="int") + self.expect_var_path("-ref", value="-2", type="int") + self.expect_var_path("+0.0", value="0") + self.expect_var_path("-0.0", value="-0") + self.expect_var_path("+enum_one", value="1") + self.expect_var_path("-enum_one", value="-1") + self.expect_var_path("+wchar", value="1") + self.expect_var_path("+char16", value="2") + self.expect_var_path("+char32", value="3") + self.expect_var_path("-bitfield.a", value="-1", type="int") + self.expect_var_path("+bitfield.a", value="1", type="int") + self.expect_var_path("+bitfield.b", value="2", type="int") + self.expect_var_path("+bitfield.c", value="3", type="unsigned int") + self.expect_var_path("+bitfield.d", value="4", type="uint64_t") diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp new file mode 100644 index 0000000000000..2c70e93433f5f --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp @@ -0,0 +1,23 @@ +#include + +int main(int argc, char **argv) { + short s = 10; + unsigned short us = 1; + + int x = 2; + int &ref = x; + enum Enum { kZero, kOne } enum_one = kOne; + wchar_t wchar = 1; + char16_t char16 = 2; + char32_t char32 = 3; + + struct BitFieldStruct { + char a : 4; + int b : 32; + unsigned int c : 32; + uint64_t d : 48; + }; + BitFieldStruct bitfield = {1, 2, 3, 4}; + + return 0; // Set a breakpoint here +} diff --git a/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/Makefile b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/Makefile new file mode 100644 index 0000000000000..99998b20bcb05 --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/TestFrameVarDILPointerArithmetic.py b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/TestFrameVarDILPointerArithmetic.py new file mode 100644 index 0000000000000..88429b370710e --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/TestFrameVarDILPointerArithmetic.py @@ -0,0 +1,29 @@ +""" +Test DIL pointer arithmetic. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from lldbsuite.test import lldbutil + + +class TestFrameVarDILPointerArithmetic(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + def test_pointer_arithmetic(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp") + ) + + self.runCmd("settings set target.experimental.use-DIL true") + + self.expect_var_path("+array", type="int *") + self.expect_var_path("+array_ref", type="int *") + self.expect_var_path("+p_int0", type="int *") + self.expect( + "frame var -- '-p_int0'", + error=True, + substrs=["invalid argument type 'int *' to unary expression"], + ) diff --git a/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/main.cpp b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/main.cpp new file mode 100644 index 0000000000000..b4e0e88b1ffc9 --- /dev/null +++ b/lldb/test/API/commands/frame/var-dil/expr/PointerArithmetic/main.cpp @@ -0,0 +1,11 @@ +void stop() {} + +int main(int argc, char **argv) { + int array[10]; + array[0] = 0; + int (&array_ref)[10] = array; + int *p_int0 = &array[0]; + + stop(); // Set a breakpoint here + return 0; +}