digitalmars.com                      
Last update Sun Mar 4 12:07:02 2018

A. Expression Evaluation

An expression comprises operands and operators, such as constants, variables, and functions. You can specify variables and functions using their symbolic names defined in your program. Digital Mars C++ supports standard language operators. This manual does not provide a complete discussion of language expressions.

Entering Expressions

The following IDDE operations prompt you to enter an expression: When one of these operations is executed, the debugger displays the Expression dialog box, shown in Figure A-1. For example, to modify a variable in the Data/Object window, you can input a new value by entering an expression. The debugger evaluates this expression and assigns the result to the variable.

Figure A-1 Expression dialog box

Symbols and Their Scope

A symbol is the name of a variable, procedure, module, or enumerated symbol in your program. You declare symbols in the scope of a procedure or module. When you use a symbol in an expression, the debugger determines its scope based on the module, procedure, and line where the current instruction is located.

The IDDE expression evaluator tries to match an entered symbol against:

If you want the debugger to search for a symbol in other procedures or modules, you must qualify the symbol by using a scope override (described below).

Scope override

You can override the current scope where the debugger looks for a symbol by qualifying the symbol with a module or a procedure name. To override the current scope, use the syntax:
	[ModuleName.][ProcName.] SymbolName 
	
The debugger looks for the symbol SymbolName in the procedure ProcName declared in the module ModuleName. For example, if you enter:
	InOut.WriteString.i
	
the debugger tries to find the symbol i in the scope of the procedure WriteString declared in the module InOut.

If you do not include the module name, the debugger uses the current module (the module containing the current instruction).

For example, if you enter:

	WriteString.i 
	
the debugger tries to find the symbol i in the scope of the procedure WriteString declared in the module displayed in the Source window.

If you specify a module name but not a procedure name, the debugger uses the global scope of the module specified. For example, if you enter:

	InOut.i
	
the debugger tries to find the symbol i in the global scope of the module InOut.

Register symbols

To evaluate processor register values, use the symbols listed in the following tables:
	Table A-1 Processor registers, 16-bit 

	Symbol		Register 

	AX or ax	AX 
	BX or bx	BX 
	CX or cx	CX 
	DX or dx	DX 
	SI or si	SI 
	DI or di	DI 
	SS or ss	SS 
	DS or ds	DS 
	CS or cs	CS 
	ES or es	ES 
	SP or sp	SP 
	BP or bp	BP 
	IP or ip	IP 
	_F or _f	Flags 
	FS		FS available only when debugging in 32-bit mode 
	GS		GS available only when debugging in 32-bit mode 


	Table A-2 Processor registers, 32-bit (available only when debugging 
	in 32-bit mode) 


	Symbol		Register 

	EAX or eax	EAX 
	EBX or ebx	EBX 
	ECX or ecx	ECX 
	EDX or edx	EDX 
	ESI or esi	ESI 
	EDI or edi	EDI 
	ESP or esp	ESP 
	EBP or ebp	EBP 
	EIP or eip	EIP 


	Table A-3 Floating point stack registers 

	Symbol		Floating point stack 

	FP0 or fp0	ST(0) 
	FP1 or fp1	ST(1) 
	FP2 or fp2	ST(2) 
	FP3 or fp3	ST(3) 
	FP4 or fp4	ST(4) 
	FP5 or fp5	ST(5) 
	FP6 or fp6	ST(6) 
	FP7 or fp7	ST(7) 
	

Operators

The IDDE supports standard C and C++ operators in expressions. These operators, described in the following sections, have the same precedence within the debugger's expression evaluator as they do in C and C++.

In addition to the standard operators in C and C++, the IDDE supports the colon operator (:). The colon operator joins a segment:offset pair of unsigned integers to specify an address value. This operator has the same priority as the unary operators.

The IDDE supports the standard C and C++ operators listed below, in descending order of precedence:

Primary

	() [] -> . this :: 
	

Unary

	* & -! ~ ++ --sizeof 
	

Binary

	.* ->* 
	* / % + -
	>> << > < >= <= 
	== != & 
	^ | 
	&& || 
	

Assignment

	 = += -= *= /= %= >>= <<= 
	&= ^= |= 
	
C expressions in the IDDE also may include typecasts of the form:
	(type-name) expression 
	
For C++, the above typecast is valid only for built-in types. Because the debugging information does not associate line numbers with local scopes, the IDDE cannot distinguish variables declared in a local scope. For example, in line 7 of the following source code:
	1 int i; 
	2 proc() 
	3 { 
	4     int i; 
	5     if (i){ 
	6         int i; 
	7         i= 5; 
	8     } 
	9 } 
	
The intent is for the variable i in i = 5 to refer to the i in line 6, but the IDDE will associate it with the i in line 4.

Considerations When Using C++ Expressions

This section describes considerations for working with the IDDE expression evaluator and C++ expressions.

The expression evaluator generally expects the same syntax as the compiler.

Access to class members

All members of a class object are accessible, no matter which type of access control is imposed (public, protected, or private), or if the object is a member of a base class (embedded object).

For example, if class Customer has a private member name, enter the following into the IDDE expression evaluator:

	Customer::name 
	
The expression evaluator provides the value of name in an output dialog box. You also can access members of an object using a pointer to the object.

For example, if the Salesperson class defines a virtual function named totalSales, redefined in the class inherited from Salesperson, totalSales can be called using a pointer to Salesperson:

	salePtr->totalSales() 
	

Ambiguous references

When an expression makes an ambiguous reference to a member name, qualify it with the class name. For example, the class Resistor is defined as follows:
	1 class Parts 
	2 { 
	3   unsigned int specs; 
	4 } resistorParts; 
	5 
	6 class Components 
	7 { 
	8   unsigned int specs; 
	9 } resistorComponents; 
	10 
	11 class Resistor: 
	12 public Parts, public Components; 
	13 { 
	14   int name; 
	15 } resistor; 
	16 ... 
	
Assume that class Resistor inherits from the Parts and Components classes. Both Parts and Components define a member item called specs. If largeResistor is an instance of class Resistor, the following expression is ambiguous:
	largeResistor.specs 
	
To resolve this problem, use either of the following expressions:

Constructors and destructors

The IDDE expression evaluator calls constructor or destructor functions just as it calls normal functions. Functions that declare or return local objects are valid expressions, and they return the address of the resulting object.

Note: The IDDE expression evaluator does not let you call the new and delete operators.

Overloaded functions

The IDDE expression evaluator supports calling overloaded functions only if an exact match exists or if the match does not need a conversion involving the construction of an object. For example, the overloaded function Print is defined as below:
	1 Print( int x) 
	2 { 
	3   ... 
	4 } 
	5 
	6 Print( float y) 
	7 { 
	8   ... 
	9 }
	
In this case, both of the following expressions for the IDDE expression evaluator are valid:

Overloaded operators

IDDE's expression evaluator lets you call an overloaded operator for user-defined types. For example, suppose you define a class that represents arrays as follows:
	class Array array1, array2, array3, array4 
	
If this class has a member function that overloads the + operator, then you can evaluate the following:
	array1 = array2 + array3 + array4 
	
Make sure that no variables overflow during evaluation. The expression evaluator automatically creates temporary objects as needed to store the intermediate values and discards them after it performs the evaluation.

Function and Procedure Calls

The IDDE lets you execute function and procedure calls defined in your program when evaluating an expression. Use this feature to: To include a function call in an expression, use the syntax:
	procedureName([param1[, param2]...]) 
	
You can specify the procedure parameters as expressions. The IDDE passes all parameters by value.

Evaluating expressions with function calls

The IDDE evaluates expressions, except for function and procedure calls, by interpretation. When the interpreter encounters a function call, it saves the application's registers and pushes its own evaluation stack onto the application program's stack. Next, the debugger orders the application to begin executing at the function's entry point. If the Flip Screen command is on, the application's screen comes to the foreground. When the application's procedure returns, the debugger takes control and restores the application's register state. During the evaluation of a procedure or a function, the debugger ignores breakpoints and watchpoints. It takes the return value and continues evaluating the expression, if necessary.

Side effects of expression evaluation

When including function or procedure calls in the IDDE expressions, beware of possible side effects caused when you evaluate a function that results in changes to your program's data. Such changes could alter the behavior of your program after it resumes execution.

Expression Evaluation Errors

The IDDE normally evaluates an expression and displays the result after you press Enter. However, with the Set Conditional Breakpoint command, the IDDE does not evaluate an expression until it reaches the breakpoint. If a run-time error occurs during the evaluation of a conditional breakpoint expression, the IDDE assumes that the expression is false and does not display an error message.

When the IDDE finds a syntax or semantic error in an expression, it displays the error message in the title bar of the debugger's main window.

Home | Compiler & Tools | Runtime Library | STL | Search | Download | Forums | Prev | Next