C++0x: Generalized constant expression / User-defined literal

From wiki.dwarfstd.org
Revision as of 16:22, 8 January 2009 by >Kendrick.wong
Jump to navigation Jump to search

For detail description of the feature, please refer to:

http://www.research.att.com/~bs/C++0xFAQ.html#constexpr

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf


Overview

The new keyword constexpr allows the user to guarantee that a data, function or object constructor is a compile-time constant. Standard allows floating-point constant expression as well. The constexpr is a new declaration specifier (not a new type) and it does not affect overloading rules. A variable or data member declared with constexpr behaves as if it was declared with const. Constant expression function must be defined before it is used, thus disallowing recursive function calls. Function parameter cannot be declared constexpr. A function declared with constexpr is not a constant expression unless all parameters are constant expression as well. A function or a constructor declared with constexpr is implicitly inline.

constexpr int Five = 5;                  // constant-expression data
constexpr int GetFive() {return 5;}      // constant-expression function
struct integer {
  constexpr integer (int a) : v(a) { }
  constexpr int val() { return v; }
private:
  int v;
};
constexpr integer numFive(5);            // constant-expression constructor
                                         // or user-defined literal

//create an array of 15 integers.
int some_value[Five+GetFive()+numFive.val()];

Proposed change to DWARF

Purpose:

  • To identify if a variable, function or object constructor can be evaluated as compile-time constants.
  • (Optional) To capture the value of the constant-expression.


New DWARF attribute:

DW_AT_const_expr 0x69 flag A compile-time constant expression


3.3.1: General Subroutine and Entry Point Information

A subroutine entry may contain a DW_AT_const_expr attribute whose value is a flag which indicates that the subroutine, under appropriate conditions, can be evaluated as a compile-time constant. Such entries may have a DW_AT_const_value attribute, whose value may be a string or any of the constant data or data block forms, as appropriate for the representation of the subroutine's return value. The value of this attribute is the actual return value of the subroutine, represented as it would be on the target architecture.

Note:

Since these constant expression subroutines will likely be inlined by the compiler, and therefore, they may not be callable within a debug session. If the return expression is simple enough, it may make sense to extend the DW_AT_const_value attribute to accept DWARF expressions to describe the semantic of the subroutine. However, I don't want to over design this in the first try, so I will delay this discussion until a later time.

For example:

constexpr int square(int x) { return x * x; }

can be described as:

  1. Push all parameters to the stack
  2. duplicate the entry on top of stack (so two x's are on top of stack)
  3. pop 2 values off the stack and multiply (effectively x*x)
<1><  yyy>      DW_TAG_subprogram
                DW_AT_type                  <xxx>
                DW_AT_const_expr            yes
                DW_AT_const_value           DW_OP_dup DW_op_mul


4.1: Data Object Entries

An entry describing a variable may have a DW_AT_const_expr attribute, whose value is a flag which indicate that the variable can be evaluated as a compile-time constant.


Example

constexpr int GetFive() {return 5;}

<1><  xxx>      DW_TAG_base_type
                DW_AT_name                  int
                DW_AT_encoding              DW_ATE_signed
<1><  yyy>      DW_TAG_subprogram
                DW_AT_type                  <xxx>
                DW_AT_const_expr            yes
                DW_AT_const_value           5