Skip to content

Consolidate unsafe-code grammar #233

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions standard/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -1263,6 +1267,7 @@ field_modifier
| 'static'
| 'readonly'
| 'volatile'
| unsafe_modifier // unsafe code support
;

variable_declarators
Expand All @@ -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.
Expand Down Expand Up @@ -1600,6 +1607,7 @@ method_modifier
| 'abstract'
| 'extern'
| 'async'
| unsafe_modifier // unsafe code support
;

return_type
Expand All @@ -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:
Expand Down Expand Up @@ -2557,6 +2567,7 @@ property_modifier
| 'override'
| 'abstract'
| 'extern'
| unsafe_modifier // unsafe code support
;

property_body
Expand All @@ -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.
Expand Down Expand Up @@ -3045,6 +3058,7 @@ event_modifier
| 'override'
| 'abstract'
| 'extern'
| unsafe_modifier // unsafe code support
;

event_accessor_declarations
Expand All @@ -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.
Expand Down Expand Up @@ -3265,6 +3281,7 @@ indexer_modifier
| 'override'
| 'abstract'
| 'extern'
| unsafe_modifier // unsafe code support
;

indexer_declarator
Expand All @@ -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.
Expand Down Expand Up @@ -3432,6 +3451,7 @@ operator_modifier
: 'public'
| 'static'
| 'extern'
| unsafe_modifier // unsafe code support
;

operator_declarator
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -3667,6 +3689,7 @@ constructor_modifier
| 'internal'
| 'private'
| 'extern'
| unsafe_modifier // unsafe code support
;

constructor_declarator
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down
3 changes: 3 additions & 0 deletions standard/delegates.md
Original file line number Diff line number Diff line change
Expand Up @@ -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*.
Expand Down
12 changes: 10 additions & 2 deletions standard/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions standard/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
8 changes: 7 additions & 1 deletion standard/statements.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
6 changes: 6 additions & 0 deletions standard/structs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)).
Expand Down Expand Up @@ -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.
Expand Down
Loading