Declarations[Decl]

9 Declarations[Decl]

9.1 Preamble[Decl.Pre]

Declarations generally specify how names are to be interpreted. Declarations have the form

declaration-seq:
declaration
declaration-seq declaration
declaration:
name-declaration
special-declaration
name-declaration:
block-declaration
function-definition
template-declaration
namespace-definition
empty-declaration
attribute-declaration
cbuffer-declaration
special-declaration:
export-declaration-group
cbuffer-member-declaration
block-declaration:
simple-declaration
namespace-alias-definition
using-declaration
using-directive
static_assert-declaration
alias-declaration
opaque-enum-declaration
empty-declaration:
;

9.2 Specifiers[Decl.Spec]

9.2.1 General[Decl.Spec.General]

The specifiers that can be used in a declaration are

decl-specifier:
storage-class-specifier
type-specifier
function-specifier
typedef
decl-specifier-seq:
decl-specifier
decl-specifier decl-specifier-seq

9.2.2 Storage Class Specifiers[Decl.Spec.Storage]

storage-class-specifier:
static
mutable

A decl-specifier-seq shall contain at most one storage-class-specifier. Any decl-specifier-seq that contains a storage-class-specifier shall not contain a typedef decl-specifier, and it shall contain an init-declarator-list that contains at least one declarator. The specified storage-class-specifier applies to the names declared by each declarator in the init-declarator-list. An explicit specialization of a template declaration may not have a storage-class-specifier.

The static specifier may be applied to names of variables at global, namespace, class and function scope and to names of functions at global, namespace, and class scope. A variable declared with the static storage class has static storage duration ([{Basic.Storage}]).

The mutable specifier may be applied to names of class data members and cannot be applied to names declared const.

9.2.3 Function specifiers[Decl.Spec.Fct]

A function-specifier can be used only in a function declaration.

function-specifier:
export
explicit

The export specifier denotes that the function has program linkage (6.7.1).

The export specifier cannot be used on functions directly or indirectly within an unnamed namespace.

Functions with program linkage can also be specified in export-declaration-group ([Decl.Export]).

If a function is declared with an export specifier then all redeclarations of the same function must also use the export specifier or be part of export-declaration-group ([Decl.Export]).

The explicit specifier may only be used on the declaration of a conversion function within a class declaration.

9.3 Declarators[Decl.Decl]

init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator initializeropt
declarator:
declarator-id attribute-specifier-seqopt
declarator parameters-and-qualifiers
declarator constant-expressionopt attribute-specifier-seqopt
parameters-and-qualifiers:
( parameter-declaration-clause ) cv-qualifier-seqopt attribute-specifier-seqopt
cv-qualifier-seq:
cv-qualifier cv-qualifier-seqopt
cv-qualifier:
const
declarator-id:
id-expression

9.3.1 Arrays[Decl.Array]

In a declaration T D where D has the form:

D1 constant-expressionopt attribute-specifier-seqopt

The type of the entity declared in a declaration T D1 is T′, the derived type T. The type of the entity declared in the declarator D is T′[N]. The constant-expression shall be a converted constant expression of unsigned integer type. Its value N specifies the number of elements in the array, called the array bound.

If present, N must be greater than zero. If not present, the declaration must be a global declaration of an object of a resource type (14), or the declarator must be followed by an initializer; otherwise the program is ill-formed. When the array bound is omitted and the declarator is followed by an initializer the bound is calculated from the number of initial elements. If a previous declaration of the entity declares a bound, a subsequent definition may omit the bound, and its bound will be the same as the earlier declaration. If a static data member of a class declares an array bound, the definition may omit it, and the bound of the declaration will be used.

9.4 Initializers[Decl.Init]

The process of initialization described in this section applies to all initializers regardless of the context.

initializer:
brace-or-equal-initializer
( expression-list )
brace-or-equal-initializer:
= initializer-clause
braced-init-list
initializer-clause:
assignment-expression
braced-init-list
braced-init-list:
{ initializer-list ,opt }
{ }
initializer-list:
initializer-clause
initializer-list , initializer-clause

9.4.1 Aggregate Initialization[Decl.Init.Agg]

An aggregate is a vector, matrix, array, or class.

The subobjects of an aggregate have a defined order. For vectors and arrays the order is increasing subscript order. For matrices it is increasing subscript order with the subscript nesting such that in the notation Mat[M][N], the ordering is Mat[0][0]...Mat[0][N]...Mat[M][0]...Mat[M][N]. For classes the order is base class, followed by member subobjects in declaration order.

A flattened ordering of subobjects can be produced by performing a depth-first traversal of the subobjects of an object following the defined subobject ordering.

Each braced initializer list is comprised of zero or more initializer-clause expressions, which is either another braced initializer list or an expression which generates a value that either is or can be implicitly converted to an rvalue. Each assignment-expression is an object, which may be a scalar or aggregate type. A flattened initializer sequence is a sequence of expressions constructed by a depth-first traversal over each assignment-expression in an initializer-list and performing a depth-first traversal accessing each subobject of the assignment-expression.

If the target object is an array of unknown size, the object is assumed to have m possible elements during parsing, where m > 0.

An initializer-list is a valid initializer if for each element En mod  m in the target object’s flattened ordering there is a corresponding expression En in the flattened initializer sequence, which can be implicitly converted to the element’s type. For arrays of unknown size, the total number of expressions in the flattened initializer sequence must be a multiple of the array’s base element type.

An initializer-list is invalid if the flattened initializer sequence contains more or fewer elements than the target object’s flattened ordering, or if any initializer In cannot be implicitly converted to the corresponding element En’s type.

9.5 Function Definitions[Decl.Functions]

Function definitions have the form:

function-definition:
attribute-specifier-seqopt decl-specifier-seqopt declarator function-body

function-body:
compound-statement

If present, the attribute-specifier-seq applies to the function.

The declarator shall be of the form:

identifier ( parameter-declaration-clause ) constopt‘ attribute-specifier-seqopt

The const qualifier shall only be allowed on non-static member functions.

9.6 Constant Buffer Declarations[Decl.cbuffer]

cbuffer-declaration:
cbuffer name resource-bindingopt { cbuffer-member-seqopt }
cbuffer-member-seq:
cbuffer-member-declaration
cbuffer-member-seq cbuffer-member-declaration
cbuffer-member-declaration:
block-declaration
function-definition
template-declaration
empty-declaration

A cbuffer declaration is declared with the cbuffer keyword. The name of the cbuffer declaration does not declare a name, and cannot be referenced from within the translation unit, nor is it required to be unique. Each cbuffer declaration refers to a unique constant buffer resource ([Resources.cnbuf]).

Declarations within a cbuffer declaration that declare names, declare their names in the scope containing the cbuffer declaration. The cbuffer declaration itself does not declare a declaration scope. A cbuffer declaration may not contain a namespace-declaration or cbuffer-declaration.

Variable declarations with program storage duration in the cbuffer declaration are called shader constants. Shader constants are implicitly const-qualified and cannot be modified in program code.