diff --git a/standard/classes.md b/standard/classes.md index 6d45c9d2b..2280c4e74 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -39,8 +39,12 @@ class_modifier | 'abstract' | 'sealed' | 'static' + | unsafe_modifier // unsafe code support ; ``` + +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + It is a compile-time error for the same modifier to appear multiple times in a class declaration. The `new` modifier is permitted on nested classes. It specifies that the class hides an inherited member by the same name, as described in [§15.3.5](classes.md#1535-the-new-modifier). It is a compile-time error for the `new` modifier to appear on a class declaration that is not a nested class declaration. @@ -1263,6 +1267,7 @@ field_modifier | 'static' | 'readonly' | 'volatile' + | unsafe_modifier // unsafe code support ; variable_declarators @@ -1274,6 +1279,8 @@ variable_declarator ; ``` +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + A *field_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)), a `new` modifier ([§15.3.5](classes.md#1535-the-new-modifier)), a valid combination of the four access modifiers ([§15.3.6](classes.md#1536-access-modifiers)), and a `static` modifier ([§15.5.2](classes.md#1552-static-and-instance-fields)). In addition, a *field_declaration* may include a `readonly` modifier ([§15.5.3](classes.md#1553-readonly-fields)) or a `volatile` modifier ([§15.5.4](classes.md#1554-volatile-fields)), but not both. The attributes and modifiers apply to all of the members declared by the *field_declaration*. It is an error for the same modifier to appear multiple times in a *field_declaration*. The *type* of a *field_declaration* specifies the type of the members introduced by the declaration. The type is followed by a list of *variable_declarator*s, each of which introduces a new member. A *variable_declarator* consists of an *Identifier* that names that member, optionally followed by an "`=`" token and a *variable_initializer* ([§15.5.6](classes.md#1556-variable-initializers)) that gives the initial value of that member. @@ -1600,6 +1607,7 @@ method_modifier | 'abstract' | 'extern' | 'async' + | unsafe_modifier // unsafe code support ; return_type @@ -1619,6 +1627,8 @@ method_body ; ``` +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + A *method_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)) and a valid combination of the four access modifiers ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.6.3](classes.md#1563-static-and-instance-methods)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods)), `override` ([§15.6.5](classes.md#1565-override-methods)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods)), `extern` ([§15.6.8](classes.md#1568-external-methods)) and `async` ([§15.15](classes.md#1515-async-functions)) modifiers. A declaration has a valid combination of modifiers if all of the following are true: @@ -2557,6 +2567,7 @@ property_modifier | 'override' | 'abstract' | 'extern' + | unsafe_modifier // unsafe code support ; property_body @@ -2569,6 +2580,8 @@ property_initializer ; ``` +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + A *property_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)) and a valid combination of the four access modifiers ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.7.2](classes.md#1572-static-and-instance-properties)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)), `override` ([§15.6.5](classes.md#1565-override-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods), [§15.7.6](classes.md#1576-virtual-sealed-override-and-abstract-accessors)), and `extern` ([§15.6.8](classes.md#1568-external-methods)) modifiers. Property declarations are subject to the same rules as method declarations ([§15.6](classes.md#156-methods)) with regard to valid combinations of modifiers. @@ -3045,6 +3058,7 @@ event_modifier | 'override' | 'abstract' | 'extern' + | unsafe_modifier // unsafe code support ; event_accessor_declarations @@ -3061,6 +3075,8 @@ remove_accessor_declaration ; ``` +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + An *event_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)) and a valid combination of the four access modifiers ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `static` ([§15.6.3](classes.md#1563-static-and-instance-methods), [§15.8.4](classes.md#1584-static-and-instance-events)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), `override` ([§15.6.5](classes.md#1565-override-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods), [§15.8.5](classes.md#1585-virtual-sealed-override-and-abstract-accessors)), and `extern` ([§15.6.8](classes.md#1568-external-methods)) modifiers. Event declarations are subject to the same rules as method declarations ([§15.6](classes.md#156-methods)) with regard to valid combinations of modifiers. @@ -3265,6 +3281,7 @@ indexer_modifier | 'override' | 'abstract' | 'extern' + | unsafe_modifier // unsafe code support ; indexer_declarator @@ -3278,6 +3295,8 @@ indexer_body ; ``` +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + An *indexer_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)) and a valid combination of the four access modifiers ([§15.3.6](classes.md#1536-access-modifiers)), the `new` ([§15.3.5](classes.md#1535-the-new-modifier)), `virtual` ([§15.6.4](classes.md#1564-virtual-methods)), `override` ([§15.6.5](classes.md#1565-override-methods)), `sealed` ([§15.6.6](classes.md#1566-sealed-methods)), `abstract` ([§15.6.7](classes.md#1567-abstract-methods)), and `extern` ([§15.6.8](classes.md#1568-external-methods)) modifiers. Indexer declarations are subject to the same rules as method declarations ([§15.6](classes.md#156-methods)) with regard to valid combinations of modifiers, with the one exception being that the `static` modifier is not permitted on an indexer declaration. @@ -3432,6 +3451,7 @@ operator_modifier : 'public' | 'static' | 'extern' + | unsafe_modifier // unsafe code support ; operator_declarator @@ -3470,6 +3490,8 @@ operator_body ``` +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + There are three categories of overloadable operators: Unary operators ([§15.10.2](classes.md#15102-unary-operators)), binary operators ([§15.10.3](classes.md#15103-binary-operators)), and conversion operators ([§15.10.4](classes.md#15104-conversion-operators)). The *operator_body* is either a semicolon, a block body ([§15.6.1](classes.md#1561-general)) or an expression body ([§15.6.1](classes.md#1561-general)). A block body consists of a *block*, which specifies the statements to execute when the operator is invoked. The *block* shall conform to the rules for value-returning methods described in [§15.6.11](classes.md#15611-method-body). An expression body consists of `=>` followed by an expression and a semicolon, and denotes a single expression to perform when the operator is invoked. @@ -3667,6 +3689,7 @@ constructor_modifier | 'internal' | 'private' | 'extern' + | unsafe_modifier // unsafe code support ; constructor_declarator @@ -3684,6 +3707,8 @@ constructor_body ; ``` +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + A *constructor_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)), a valid combination of the four access modifiers ([§15.3.6](classes.md#1536-access-modifiers)), and an `extern` ([§15.6.8](classes.md#1568-external-methods)) modifier. A constructor declaration is not permitted to include the same modifier multiple times. The *Identifier* of a *constructor_declarator* shall name the class in which the instance constructor is declared. If any other name is specified, a compile-time error occurs. @@ -3882,8 +3907,13 @@ static_constructor_declaration ; static_constructor_modifiers - : 'extern'? 'static' - | 'static' 'extern'? + : 'static' + | 'static' 'extern' unsafe_modifier? + | 'static' unsafe_modifier 'extern'? + | 'extern' 'static' unsafe_modifier? + | 'extern' unsafe_modifier 'static' + | unsafe_modifier 'static' 'extern'? + | unsafe_modifier 'extern' 'static' ; static_constructor_body @@ -3892,6 +3922,8 @@ static_constructor_body ; ``` +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + A *static_constructor_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)) and an `extern` modifier ([§15.6.8](classes.md#1568-external-methods)). The *Identifier* of a *static_constructor_declaration* shall name the class in which the static constructor is declared. If any other name is specified, a compile-time error occurs. @@ -3998,7 +4030,9 @@ A ***finalizer*** is a member that implements the actions required to finalize a ```ANTLR finalizer_declaration - : attributes? 'extern'? '~' Identifier '(' ')' finalizer_body + : attributes? '~' Identifier '(' ')' finalizer_body + | attributes? 'extern' unsafe_modifier? '~' Identifier '(' ')' finalizer_body + | attributes? unsafe_modifier 'extern'? '~' Identifier '(' ')' finalizer_body ; finalizer_body @@ -4007,6 +4041,8 @@ finalizer_body ; ``` +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + A *finalizer_declaration* may include a set of *attributes* ([§22](attributes.md#22-attributes)). The *Identifier* of a *finalizer_declarator* shall name the class in which the finalizer is declared. If any other name is specified, a compile-time error occurs. diff --git a/standard/delegates.md b/standard/delegates.md index ca288e227..00658d077 100644 --- a/standard/delegates.md +++ b/standard/delegates.md @@ -21,9 +21,12 @@ delegate_modifier | 'protected' | 'internal' | 'private' + | unsafe_modifier // unsafe code support ; ``` +*unsafe_modifier* is defined in [§23.2](unsafe-code.md#232-unsafe-contexts). + It is a compile-time error for the same modifier to appear multiple times in a delegate declaration. A delegate declaration shall not supply any *type_parameter_constraints_clause*s unless it also supplies a *variant_type_parameter_list*. diff --git a/standard/expressions.md b/standard/expressions.md index 8260da5fa..f4fde9f8d 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -1124,9 +1124,13 @@ primary_no_array_creation_expression | default_value_expression | nameof_expression | anonymous_method_expression + | pointer_member_access // unsafe code support + | pointer_element_access // unsafe code support ; ``` +*pointer_member_access* ([§23.6.3](unsafe-code.md#2363-pointer-member-access)) and *pointer_element_access* ([§23.6.4](unsafe-code.md#2364-pointer-element-access)) are only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + Primary expressions are divided between *array_creation_expression*s and *primary_no_array_creation_expression*s. Treating *array_creation_expression* in this way, rather than listing it along with the other simple expression forms, enables the grammar to disallow potentially confusing code such as ```csharp @@ -2050,7 +2054,7 @@ class __Anonymous1 } ``` -where each «Tx» is the type of the corresponding expression «ex». The expression used in a *member-declarator* shall have a type. Thus, it is a compile-time error for an expression in a *member-declarator* to be `null` or an anonymous function. It is also a compile-time error for the expression to have an unsafe type. +where each «Tx» is the type of the corresponding expression «ex». The expression used in a *member-declarator* shall have a type. Thus, it is a compile-time error for an expression in a *member-declarator* to be `null` or an anonymous function. It is also a compile-time error for the expression to have a pointer type ([§23.3](unsafe-code.md#233-pointer-types)). The names of an anonymous type and of the parameter to its `Equals` method are automatically generated by the compiler and cannot be referenced in program text. @@ -2169,7 +2173,7 @@ The `typeof` operator can be used on a type parameter. The result is the `System ### 12.7.13 The sizeof operator -The `sizeof` operator returns the number of 8-bit bytes occupied by a variable of a given type. The type specified as an operand to sizeof shall be an *unmanaged_type* ([§23.3](unsafe-code.md#233-pointer-types)). +The `sizeof` operator returns the number of 8-bit bytes occupied by a variable of a given type. The type specified as an operand to sizeof shall be an *unmanaged_type* ($unmanaged-types-new-clause). ```ANTLR sizeof_expression @@ -2417,9 +2421,13 @@ unary_expression | pre_decrement_expression | cast_expression | await_expression + | pointer_indirection_expression // unsafe code support + | addressof_expression // unsafe code support ; ``` +*pointer_indirection_expression* ([§23.6.2](unsafe-code.md#2362-pointer-indirection)) and *addressof_expression* ([§23.6.5](unsafe-code.md#2365-the-address-of-operator)) are available only in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + If the operand of a *unary_expression* has the compile-time type `dynamic`, it is dynamically bound ([§12.3.3](expressions.md#1233-dynamic-binding)). In this case, the compile-time type of the *unary_expression* is `dynamic`, and the resolution described below will take place at run-time using the run-time type of the operand. ### 12.8.2 Unary plus operator diff --git a/standard/interfaces.md b/standard/interfaces.md index 068fe83c2..156ce61f0 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -35,9 +35,12 @@ interface_modifier | 'protected' | 'internal' | 'private' + | unsafe_modifier // unsafe code support ; ``` +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + It is a compile-time error for the same modifier to appear multiple times in an interface declaration. The `new` modifier is only permitted on interfaces defined within a class. It specifies that the interface hides an inherited member by the same name, as described in [§15.3.5](classes.md#1535-the-new-modifier). diff --git a/standard/statements.md b/standard/statements.md index 84be2e569..ee089191c 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -26,9 +26,12 @@ embedded_statement | lock_statement | using_statement | yield_statement + | unsafe_statement // unsafe code support + | fixed_statement // unsafe code support ; ``` - +*unsafe_statement* ([§23.2](unsafe-code.md#232-unsafe-contexts)) and *fixed_statement* ([§23.7](unsafe-code.md#237-the-fixed-statement)) are only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + The *embedded_statement* nonterminal is used for statements that appear within other statements. The use of *embedded_statement* rather than *statement* excludes the use of declaration statements and labeled statements in these contexts. > *Example*: The code @@ -257,9 +260,12 @@ local_variable_declarator local_variable_initializer : expression | array_initializer + | stackalloc_initializer // unsafe code support ; ``` +*stackalloc_initializer* ([§23.9](unsafe-code.md#239-stack-allocation)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + The *local_variable_type* of a *local_variable_declaration* either directly specifies the type of the variables introduced by the declaration, or indicates with the identifier `var` that the type should be inferred based on an initializer. The type is followed by a list of *local_variable_declarator*s, each of which introduces a new variable. A *local_variable_declarator* consists of an *Identifier* that names the variable, optionally followed by an "`=`" token and a *local_variable_initializer* that gives the initial value of the variable. In the context of a local variable declaration, the identifier `var` acts as a contextual keyword ([§7.4.4](lexical-structure.md#744-keywords)).When the *local_variable_type* is specified as `var` and no type named `var` is in scope, the declaration is an ***implicitly typed local variable declaration***, whose type is inferred from the type of the associated initializer expression. Implicitly typed local variable declarations are subject to the following restrictions: diff --git a/standard/structs.md b/standard/structs.md index ead365be2..6cb59cc90 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -38,9 +38,12 @@ struct_modifier | 'protected' | 'internal' | 'private' + | unsafe_modifier // unsafe code support ; ``` +*unsafe_modifier* ([§23.2](unsafe-code.md#232-unsafe-contexts)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + It is a compile-time error for the same modifier to appear multiple times in a struct declaration. The modifiers of a struct declaration have the same meaning as those of a class declaration ([§15.2.2](classes.md#1522-class-modifiers)). @@ -89,9 +92,12 @@ struct_member_declaration | constructor_declaration | static_constructor_declaration | type_declaration + | fixed_size_buffer_declaration // unsafe code support ; ``` +*fixed_size_buffer_declaration* ([§23.8.2](unsafe-code.md#2382-fixed-size-buffer-declarations)) is only available in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). + > *Note*: All kinds of *class_member_declaration*s except *finalizer_declaration* are also *struct_member_declaration*s. *end note* Except for the differences noted in [§16.4](structs.md#164-class-and-struct-differences), the descriptions of class members provided in [§15.3](classes.md#153-class-members) through [§15.12](classes.md#1512-static-constructors) apply to struct members as well. diff --git a/standard/types.md b/standard/types.md index 1b7727ae0..1a2393224 100644 --- a/standard/types.md +++ b/standard/types.md @@ -9,10 +9,11 @@ type : reference_type | value_type | type_parameter + | pointer_type // unsafe code support ; ``` -A third category of types, pointers, is available only in unsafe code [§23.3](unsafe-code.md#233-pointer-types). +*pointer_type* ([§23.3](unsafe-code.md#233-pointer-types)) is available only in unsafe code ([§23](unsafe-code.md#23-unsafe-code)). Value types differ from reference types in that variables of the value types directly contain their data, whereas variables of the reference types store ***references*** to their data, the latter being known as ***objects***. With reference types, it is possible for two variables to reference the same object, and thus possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other. @@ -56,6 +57,7 @@ non_array_type | delegate_type | 'dynamic' | type_parameter + | pointer_type // unsafe code support ; rank_specifier @@ -67,6 +69,8 @@ delegate_type ; ``` +*pointer_type* is available only in unsafe code ([§23.3](unsafe-code.md#233-pointer-types)). + A reference type value is a reference to an ***instance*** of the type, the latter known as an ***object***. The special value `null` is compatible with all reference types and indicates the absence of an instance. ### 9.2.2 Class types @@ -440,7 +444,7 @@ The detailed rules for name lookup in the *namespace_or_type_name* productions i > ``` > *end example* -A non-enum constructed type shall not be used as an *unmanaged_type* [§23.3](unsafe-code.md#233-pointer-types). +A non-enum constructed type shall not be used as an *unmanaged_type* ($unmanaged-types-new-clause). ### 9.4.2 Type arguments @@ -539,7 +543,7 @@ Since a type parameter can be instantiated with many different type arguments, t > - A `new` expression [§12.7.11.2](expressions.md#127112-object-creation-expressions) can only be used with a type parameter if the type parameter is constrained by a *constructor_constraint* or the value type constraint [§15.2.5](classes.md#1525-type-parameter-constraints). > - A type parameter cannot be used anywhere within an attribute. > - A type parameter cannot be used in a member access [§12.7.5](expressions.md#1275-member-access) or type name [§8.8](basic-concepts.md#88-namespace-and-type-names) to identify a static member or a nested type. -> - A type parameter cannot be used as an *unmanaged_type* [§23.3](unsafe-code.md#233-pointer-types). *end note* +> - A type parameter cannot be used as an *unmanaged_type* ($unmanaged-types-new-clause). *end note* As a type, type parameters are purely a compile-time construct. At run-time, each type parameter is bound to a run-time type that was specified by supplying a type argument to the generic type declaration. Thus, the type of a variable declared with a type parameter will, at run-time, be a closed constructed type [§9.4.3](types.md#943-open-and-closed-types). The run-time execution of all statements and expressions involving type parameters uses the type that was supplied as the type argument for that parameter. @@ -603,3 +607,18 @@ Because of this equivalence, the following holds: - Signatures that are the same when replacing `dynamic` with `object` are considered the same signature. - The type `dynamic` is indistinguishable from `object` at run-time. - An expression of the type `dynamic` is referred to as a ***dynamic expression***. + +## §unmanaged-types-new-clause Unmanaged types + +```ANTLR +unmanaged_type + : type + ; +``` + +An *unmanaged_type* is any type that isn't a *reference_type*, a *type_parameter*, or a constructed type, and contains no fields whose type is not an *unmanaged_type*. In other words, an *unmanaged_type* is one of the following: + - `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `char`, `float`, `double`, `decimal`, or `bool`. + - Any *enum_type*. + - Any user-defined *struct_type* that is not a constructed type and contains fields of *unmanaged_type*s only. + - In unsafe code ([§23.2](unsafe-code.md#232-unsafe-contexts)), any *pointer_type* ([§23.3](unsafe-code.md#233-pointer-types)). + diff --git a/standard/unsafe-code.md b/standard/unsafe-code.md index bf205b820..52529a3b7 100644 --- a/standard/unsafe-code.md +++ b/standard/unsafe-code.md @@ -2,7 +2,7 @@ ## 23.1 General -An implementation that does not support unsafe code is required to diagnose any usage of the keyword `unsafe`. +An implementation that does not support unsafe code is required to diagnose any usage of the syntactic rules defined in this clause. **The remainder of this clause, including all of its subclauses, is conditionally normative.** @@ -23,82 +23,11 @@ The unsafe features of C# are available only in unsafe contexts. An unsafe conte - A declaration of a field, method, property, event, indexer, operator, instance constructor, finalizer, or static constructor may include an `unsafe` modifier, in which case, the entire textual extent of that member declaration is considered an unsafe context. - An *unsafe_statement* enables the use of an unsafe context within a *block*. The entire textual extent of the associated *block* is considered an unsafe context. -The associated grammar extensions are shown below. For brevity, ellipses (...) are used to represent productions that appear in preceding clauses. +The associated grammar extensions are shown below and in subsequent subclauses. ```ANTLR -class_modifier - : '...' - | 'unsafe' - ; - -struct_modifier - : '...' - | 'unsafe' - ; - -interface_modifier - : '...' - | 'unsafe' - ; - -delegate_modifier - : '...' - | 'unsafe' - ; - -field_modifier - : '...' - | 'unsafe' - ; - -method_modifier - : '...' - | 'unsafe' - ; - -property_modifier - : '...' - | 'unsafe' - ; - -event_modifier - : '...' - | 'unsafe' - ; - -indexer_modifier - : '...' - | 'unsafe' - ; - -operator_modifier - : '...' - | 'unsafe' - ; - -constructor_modifier - : '...' - | 'unsafe' - ; - -finalizer_declaration - : attributes? 'extern'? 'unsafe'? '~' identifier '(' ')' finalizer_body - | attributes? 'unsafe'? 'extern'? '~' identifier '(' ')' finalizer_body - ; - -static_constructor_modifiers - : 'extern'? 'unsafe'? 'static' - | 'unsafe'? 'extern'? 'static' - | 'extern'? 'static' 'unsafe'? - | 'unsafe'? 'static' 'extern'? - | 'static' 'extern'? 'unsafe'? - | 'static' 'unsafe'? 'extern'? - ; - -embedded_statement - : '...' - | unsafe_statement - | fixed_statement +unsafe_modifier + : 'unsafe' ; unsafe_statement @@ -166,29 +95,13 @@ When the `unsafe` modifier is used on a partial type declaration ([§15.2.7](cla In an unsafe context, a *type* ([§9.1](types.md#91-general)) can be a *pointer_type* as well as a *value_type*, a *reference_type*, or a *type_parameter*. In an unsafe context a pointer-type may also be the element type of an array ([§17](arrays.md#17-arrays)). A *pointer-type* may also be used in a typeof expression ([§12.7.12](expressions.md#12712-the-typeof-operator)) outside of an unsafe context (as such usage is not unsafe). -```ANTLR -type - : '...' - | pointer_type - ; - -non_array_type - : '...' - | pointer_type - ; -``` - -A *pointer_type* is written as an *unmanaged_type* or the keyword `void`, followed by a `*` token: +A *pointer_type* is written as an *unmanaged_type* ($unmanaged-types-new-clause) or the keyword `void`, followed by a `*` token: ```ANTLR pointer_type : unmanaged_type '*' | 'void' '*' ; - -unmanaged_type - : type - ; ``` The type specified before the `*` in a pointer type is called the ***referent type*** of the pointer type. It represents the type of the variable to which a value of the pointer type points. @@ -409,23 +322,7 @@ The variables `a`, `i0`, `i1`, ... `in` are not visible to or accessible to `x` In an unsafe context, an expression may yield a result of a pointer type, but outside an unsafe context, it is a compile-time error for an expression to be of a pointer type. In precise terms, outside an unsafe context a compile-time error occurs if any *simple_name* ([§12.7.3](expressions.md#1273-simple-names)), *member_access* ([§12.7.5](expressions.md#1275-member-access)), *invocation_expression* ([§12.7.6](expressions.md#1276-invocation-expressions)), or *element_access* ([§12.7.7](expressions.md#1277-element-access)) is of a pointer type. -In an unsafe context, the *primary_no_array_creation_expression* ([§12.7](expressions.md#127-primary-expressions)) and *unary_expression* ([§12.8](expressions.md#128-unary-operators)) productions permit the following additional constructs: - -```ANTLR -primary_no_array_creation_expression - : '...' - | pointer_member_access - | pointer_element_access - ; - -unary_expression - : '...' - | pointer_indirection_expression - | addressof_expression - ; -``` - -These constructs are described in the following subclauses. +In an unsafe context, the *primary_no_array_creation_expression* ([§12.7](expressions.md#127-primary-expressions)) and *unary_expression* ([§12.8](expressions.md#128-unary-operators)) productions permit additional constructs, which are described in the following subclauses. > *Note*: The precedence and associativity of the unsafe operators is implied by the grammar. *end note* @@ -837,11 +734,6 @@ A ***fixed-size buffer*** is a member that represents storage for a fixed-length Fixed-size buffers are only permitted in struct declarations and may only occur in unsafe contexts ([§23.2](unsafe-code.md#232-unsafe-contexts)). ```ANTLR -struct_member_declaration - : '...' - | fixed_size_buffer_declaration - ; - fixed_size_buffer_declaration : attributes? fixed_size_buffer_modifier* 'fixed' buffer_element_type fixed_size_buffer_declarator+ ';' ; @@ -947,17 +839,12 @@ When the outermost containing struct variable of a fixed-size buffer member is a In an unsafe context, a local variable declaration ([§13.6.2](statements.md#1362-local-variable-declarations)) may include a stack allocation initializer, which allocates memory from the call stack. ```ANTLR -local_variable_initializer - : '...' - | stackalloc_initializer - ; - stackalloc_initializer : 'stackalloc' unmanaged_type '[' expression ']' ; ``` -The *unmanaged_type* indicates the type of the items that will be stored in the newly allocated location, and the *expression* indicates the number of these items. Taken together, these specify the required allocation size. Since the size of a stack allocation cannot be negative, it is a compile-time error to specify the number of items as a *constant_expression* that evaluates to a negative value. +The *unmanaged_type* ($unmanaged-types-new-clause) indicates the type of the items that will be stored in the newly allocated location, and the *expression* indicates the number of these items. Taken together, these specify the required allocation size. Since the size of a stack allocation cannot be negative, it is a compile-time error to specify the number of items as a *constant_expression* that evaluates to a negative value. A stack allocation initializer of the form stackalloc `T[E]` requires `T` to be an unmanaged type ([§23.3](unsafe-code.md#233-pointer-types)) and `E` to be an expression implicitly convertible to type int. The construct allocates `E * sizeof(T)` bytes from the call stack and returns a pointer, of type `T*`, to the newly allocated block. If `E` is a negative value, then the behavior is undefined. If `E` is zero, then no allocation is made, and the pointer returned is implementation-defined. If there is not enough memory available to allocate a block of the given size, a `System.StackOverflowException` is thrown.