diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
index ed6e1a9cc2af0..2e6e1e10bc39b 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
+++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
@@ -6180,6 +6180,15 @@ internal static string ERR_InvalidFormatForGuidForOption {
}
}
+ ///
+ /// Looks up a localized string similar to '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'..
+ ///
+ internal static string ERR_InvalidFunctionPointerCallingConvention {
+ get {
+ return ResourceManager.GetString("ERR_InvalidFunctionPointerCallingConvention", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Invalid type specified as an argument for TypeForwardedTo attribute.
///
@@ -11374,6 +11383,15 @@ internal static string IDS_FeatureFixedBuffer {
}
}
+ ///
+ /// Looks up a localized string similar to function pointers.
+ ///
+ internal static string IDS_FeatureFunctionPointers {
+ get {
+ return ResourceManager.GetString("IDS_FeatureFunctionPointers", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to generics.
///
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index b06d12164a68f..ac3749a5e954e 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -5945,6 +5945,12 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
Command-line syntax error: '{0}' is not a valid value for the '{1}' option. The value must be of the form '{2}'.
+
+ function pointers
+
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
Internal error in the C# compiler.
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index e5d2405fbf9ac..77ebe952bb9f7 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -1736,6 +1736,12 @@ internal enum ErrorCode
ERR_InternalError = 8751,
+ #region diagnostics introduced in preview
+
+ ERR_InvalidFunctionPointerCallingConvention = 8752,
+
+ #endregion
+
// Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd)
}
}
diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
index 402907c2c08a7..f60f831e5567b 100644
--- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs
+++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
@@ -185,6 +185,7 @@ internal enum MessageID
IDS_FeatureSwitchExpression = MessageBase + 12763,
IDS_FeatureAsyncUsing = MessageBase + 12764,
IDS_FeatureLambdaDiscardParameters = MessageBase + 12765,
+ IDS_FeatureFunctionPointers = MessageBase + 12766,
}
// Message IDs may refer to strings that need to be localized.
@@ -293,6 +294,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)
{
// Preview features.
case MessageID.IDS_FeatureLambdaDiscardParameters: // semantic check
+ case MessageID.IDS_FeatureFunctionPointers:
return LanguageVersion.Preview;
// C# 8.0 features.
diff --git a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4 b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4
index d5c72f4d4b4ea..3b1a021eaced2 100644
--- a/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4
+++ b/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4
@@ -318,6 +318,7 @@ namespace_declaration
type
: array_type
+ | function_pointer_type
| name
| nullable_type
| omitted_type_argument
@@ -335,6 +336,14 @@ array_rank_specifier
: '[' (expression (',' expression)*)? ']'
;
+function_pointer_type
+ : 'delegate' '*' syntax_token? '<' modified_type (',' modified_type)* '>'
+ ;
+
+modified_type
+ : modifier* type
+ ;
+
nullable_type
: type '?'
;
diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs
index 8b16e6b6abf15..dff4b836e2512 100644
--- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Internal.Generated.cs
@@ -1048,6 +1048,302 @@ static PointerTypeSyntax()
}
}
+ internal sealed partial class FunctionPointerTypeSyntax : TypeSyntax
+ {
+ internal readonly SyntaxToken delegateKeyword;
+ internal readonly SyntaxToken asteriskToken;
+ internal readonly SyntaxToken? callingConvention;
+ internal readonly SyntaxToken lessThanToken;
+ internal readonly GreenNode? arguments;
+ internal readonly SyntaxToken greaterThanToken;
+
+ internal FunctionPointerTypeSyntax(SyntaxKind kind, SyntaxToken delegateKeyword, SyntaxToken asteriskToken, SyntaxToken? callingConvention, SyntaxToken lessThanToken, GreenNode? arguments, SyntaxToken greaterThanToken, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
+ : base(kind, diagnostics, annotations)
+ {
+ this.SlotCount = 6;
+ this.AdjustFlagsAndWidth(delegateKeyword);
+ this.delegateKeyword = delegateKeyword;
+ this.AdjustFlagsAndWidth(asteriskToken);
+ this.asteriskToken = asteriskToken;
+ if (callingConvention != null)
+ {
+ this.AdjustFlagsAndWidth(callingConvention);
+ this.callingConvention = callingConvention;
+ }
+ this.AdjustFlagsAndWidth(lessThanToken);
+ this.lessThanToken = lessThanToken;
+ if (arguments != null)
+ {
+ this.AdjustFlagsAndWidth(arguments);
+ this.arguments = arguments;
+ }
+ this.AdjustFlagsAndWidth(greaterThanToken);
+ this.greaterThanToken = greaterThanToken;
+ }
+
+ internal FunctionPointerTypeSyntax(SyntaxKind kind, SyntaxToken delegateKeyword, SyntaxToken asteriskToken, SyntaxToken? callingConvention, SyntaxToken lessThanToken, GreenNode? arguments, SyntaxToken greaterThanToken, SyntaxFactoryContext context)
+ : base(kind)
+ {
+ this.SetFactoryContext(context);
+ this.SlotCount = 6;
+ this.AdjustFlagsAndWidth(delegateKeyword);
+ this.delegateKeyword = delegateKeyword;
+ this.AdjustFlagsAndWidth(asteriskToken);
+ this.asteriskToken = asteriskToken;
+ if (callingConvention != null)
+ {
+ this.AdjustFlagsAndWidth(callingConvention);
+ this.callingConvention = callingConvention;
+ }
+ this.AdjustFlagsAndWidth(lessThanToken);
+ this.lessThanToken = lessThanToken;
+ if (arguments != null)
+ {
+ this.AdjustFlagsAndWidth(arguments);
+ this.arguments = arguments;
+ }
+ this.AdjustFlagsAndWidth(greaterThanToken);
+ this.greaterThanToken = greaterThanToken;
+ }
+
+ internal FunctionPointerTypeSyntax(SyntaxKind kind, SyntaxToken delegateKeyword, SyntaxToken asteriskToken, SyntaxToken? callingConvention, SyntaxToken lessThanToken, GreenNode? arguments, SyntaxToken greaterThanToken)
+ : base(kind)
+ {
+ this.SlotCount = 6;
+ this.AdjustFlagsAndWidth(delegateKeyword);
+ this.delegateKeyword = delegateKeyword;
+ this.AdjustFlagsAndWidth(asteriskToken);
+ this.asteriskToken = asteriskToken;
+ if (callingConvention != null)
+ {
+ this.AdjustFlagsAndWidth(callingConvention);
+ this.callingConvention = callingConvention;
+ }
+ this.AdjustFlagsAndWidth(lessThanToken);
+ this.lessThanToken = lessThanToken;
+ if (arguments != null)
+ {
+ this.AdjustFlagsAndWidth(arguments);
+ this.arguments = arguments;
+ }
+ this.AdjustFlagsAndWidth(greaterThanToken);
+ this.greaterThanToken = greaterThanToken;
+ }
+
+ /// SyntaxToken representing the delegate keyword.
+ public SyntaxToken DelegateKeyword => this.delegateKeyword;
+ /// SyntaxToken representing the asterisk.
+ public SyntaxToken AsteriskToken => this.asteriskToken;
+ /// SyntaxToken representing the optional calling convention.
+ public SyntaxToken? CallingConvention => this.callingConvention;
+ /// SyntaxToken representing the less than token.
+ public SyntaxToken LessThanToken => this.lessThanToken;
+ /// SeparatedSyntaxList of ModifiedTypes representing the list of parameters and return type.
+ public Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList Arguments => new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(this.arguments));
+ /// SyntaxToken representing the greater than token.
+ public SyntaxToken GreaterThanToken => this.greaterThanToken;
+
+ internal override GreenNode? GetSlot(int index)
+ => index switch
+ {
+ 0 => this.delegateKeyword,
+ 1 => this.asteriskToken,
+ 2 => this.callingConvention,
+ 3 => this.lessThanToken,
+ 4 => this.arguments,
+ 5 => this.greaterThanToken,
+ _ => null,
+ };
+
+ internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.FunctionPointerTypeSyntax(this, parent, position);
+
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitFunctionPointerType(this);
+ public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitFunctionPointerType(this);
+
+ public FunctionPointerTypeSyntax Update(SyntaxToken delegateKeyword, SyntaxToken asteriskToken, SyntaxToken callingConvention, SyntaxToken lessThanToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList arguments, SyntaxToken greaterThanToken)
+ {
+ if (delegateKeyword != this.DelegateKeyword || asteriskToken != this.AsteriskToken || callingConvention != this.CallingConvention || lessThanToken != this.LessThanToken || arguments != this.Arguments || greaterThanToken != this.GreaterThanToken)
+ {
+ var newNode = SyntaxFactory.FunctionPointerType(delegateKeyword, asteriskToken, callingConvention, lessThanToken, arguments, greaterThanToken);
+ var diags = GetDiagnostics();
+ if (diags?.Length > 0)
+ newNode = newNode.WithDiagnosticsGreen(diags);
+ var annotations = GetAnnotations();
+ if (annotations?.Length > 0)
+ newNode = newNode.WithAnnotationsGreen(annotations);
+ return newNode;
+ }
+
+ return this;
+ }
+
+ internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
+ => new FunctionPointerTypeSyntax(this.Kind, this.delegateKeyword, this.asteriskToken, this.callingConvention, this.lessThanToken, this.arguments, this.greaterThanToken, diagnostics, GetAnnotations());
+
+ internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
+ => new FunctionPointerTypeSyntax(this.Kind, this.delegateKeyword, this.asteriskToken, this.callingConvention, this.lessThanToken, this.arguments, this.greaterThanToken, GetDiagnostics(), annotations);
+
+ internal FunctionPointerTypeSyntax(ObjectReader reader)
+ : base(reader)
+ {
+ this.SlotCount = 6;
+ var delegateKeyword = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(delegateKeyword);
+ this.delegateKeyword = delegateKeyword;
+ var asteriskToken = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(asteriskToken);
+ this.asteriskToken = asteriskToken;
+ var callingConvention = (SyntaxToken?)reader.ReadValue();
+ if (callingConvention != null)
+ {
+ AdjustFlagsAndWidth(callingConvention);
+ this.callingConvention = callingConvention;
+ }
+ var lessThanToken = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(lessThanToken);
+ this.lessThanToken = lessThanToken;
+ var arguments = (GreenNode?)reader.ReadValue();
+ if (arguments != null)
+ {
+ AdjustFlagsAndWidth(arguments);
+ this.arguments = arguments;
+ }
+ var greaterThanToken = (SyntaxToken)reader.ReadValue();
+ AdjustFlagsAndWidth(greaterThanToken);
+ this.greaterThanToken = greaterThanToken;
+ }
+
+ internal override void WriteTo(ObjectWriter writer)
+ {
+ base.WriteTo(writer);
+ writer.WriteValue(this.delegateKeyword);
+ writer.WriteValue(this.asteriskToken);
+ writer.WriteValue(this.callingConvention);
+ writer.WriteValue(this.lessThanToken);
+ writer.WriteValue(this.arguments);
+ writer.WriteValue(this.greaterThanToken);
+ }
+
+ static FunctionPointerTypeSyntax()
+ {
+ ObjectBinder.RegisterTypeReader(typeof(FunctionPointerTypeSyntax), r => new FunctionPointerTypeSyntax(r));
+ }
+ }
+
+ internal sealed partial class ModifiedType : CSharpSyntaxNode
+ {
+ internal readonly GreenNode? modifiers;
+ internal readonly TypeSyntax type;
+
+ internal ModifiedType(SyntaxKind kind, GreenNode? modifiers, TypeSyntax type, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations)
+ : base(kind, diagnostics, annotations)
+ {
+ this.SlotCount = 2;
+ if (modifiers != null)
+ {
+ this.AdjustFlagsAndWidth(modifiers);
+ this.modifiers = modifiers;
+ }
+ this.AdjustFlagsAndWidth(type);
+ this.type = type;
+ }
+
+ internal ModifiedType(SyntaxKind kind, GreenNode? modifiers, TypeSyntax type, SyntaxFactoryContext context)
+ : base(kind)
+ {
+ this.SetFactoryContext(context);
+ this.SlotCount = 2;
+ if (modifiers != null)
+ {
+ this.AdjustFlagsAndWidth(modifiers);
+ this.modifiers = modifiers;
+ }
+ this.AdjustFlagsAndWidth(type);
+ this.type = type;
+ }
+
+ internal ModifiedType(SyntaxKind kind, GreenNode? modifiers, TypeSyntax type)
+ : base(kind)
+ {
+ this.SlotCount = 2;
+ if (modifiers != null)
+ {
+ this.AdjustFlagsAndWidth(modifiers);
+ this.modifiers = modifiers;
+ }
+ this.AdjustFlagsAndWidth(type);
+ this.type = type;
+ }
+
+ /// SyntaxList of the optional modifier keywords.
+ public Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList Modifiers => new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(this.modifiers);
+ /// TypeSyntax representing the modified type.
+ public TypeSyntax Type => this.type;
+
+ internal override GreenNode? GetSlot(int index)
+ => index switch
+ {
+ 0 => this.modifiers,
+ 1 => this.type,
+ _ => null,
+ };
+
+ internal override SyntaxNode CreateRed(SyntaxNode? parent, int position) => new CSharp.Syntax.ModifiedType(this, parent, position);
+
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitModifiedType(this);
+ public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitModifiedType(this);
+
+ public ModifiedType Update(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList modifiers, TypeSyntax type)
+ {
+ if (modifiers != this.Modifiers || type != this.Type)
+ {
+ var newNode = SyntaxFactory.ModifiedType(modifiers, type);
+ var diags = GetDiagnostics();
+ if (diags?.Length > 0)
+ newNode = newNode.WithDiagnosticsGreen(diags);
+ var annotations = GetAnnotations();
+ if (annotations?.Length > 0)
+ newNode = newNode.WithAnnotationsGreen(annotations);
+ return newNode;
+ }
+
+ return this;
+ }
+
+ internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)
+ => new ModifiedType(this.Kind, this.modifiers, this.type, diagnostics, GetAnnotations());
+
+ internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
+ => new ModifiedType(this.Kind, this.modifiers, this.type, GetDiagnostics(), annotations);
+
+ internal ModifiedType(ObjectReader reader)
+ : base(reader)
+ {
+ this.SlotCount = 2;
+ var modifiers = (GreenNode?)reader.ReadValue();
+ if (modifiers != null)
+ {
+ AdjustFlagsAndWidth(modifiers);
+ this.modifiers = modifiers;
+ }
+ var type = (TypeSyntax)reader.ReadValue();
+ AdjustFlagsAndWidth(type);
+ this.type = type;
+ }
+
+ internal override void WriteTo(ObjectWriter writer)
+ {
+ base.WriteTo(writer);
+ writer.WriteValue(this.modifiers);
+ writer.WriteValue(this.type);
+ }
+
+ static ModifiedType()
+ {
+ ObjectBinder.RegisterTypeReader(typeof(ModifiedType), r => new ModifiedType(r));
+ }
+ }
+
/// Class which represents the syntax node for a nullable type.
internal sealed partial class NullableTypeSyntax : TypeSyntax
{
@@ -30234,6 +30530,8 @@ internal partial class CSharpSyntaxVisitor
public virtual TResult VisitArrayType(ArrayTypeSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitArrayRankSpecifier(ArrayRankSpecifierSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitPointerType(PointerTypeSyntax node) => this.DefaultVisit(node);
+ public virtual TResult VisitFunctionPointerType(FunctionPointerTypeSyntax node) => this.DefaultVisit(node);
+ public virtual TResult VisitModifiedType(ModifiedType node) => this.DefaultVisit(node);
public virtual TResult VisitNullableType(NullableTypeSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitTupleType(TupleTypeSyntax node) => this.DefaultVisit(node);
public virtual TResult VisitTupleElement(TupleElementSyntax node) => this.DefaultVisit(node);
@@ -30453,6 +30751,8 @@ internal partial class CSharpSyntaxVisitor
public virtual void VisitArrayType(ArrayTypeSyntax node) => this.DefaultVisit(node);
public virtual void VisitArrayRankSpecifier(ArrayRankSpecifierSyntax node) => this.DefaultVisit(node);
public virtual void VisitPointerType(PointerTypeSyntax node) => this.DefaultVisit(node);
+ public virtual void VisitFunctionPointerType(FunctionPointerTypeSyntax node) => this.DefaultVisit(node);
+ public virtual void VisitModifiedType(ModifiedType node) => this.DefaultVisit(node);
public virtual void VisitNullableType(NullableTypeSyntax node) => this.DefaultVisit(node);
public virtual void VisitTupleType(TupleTypeSyntax node) => this.DefaultVisit(node);
public virtual void VisitTupleElement(TupleElementSyntax node) => this.DefaultVisit(node);
@@ -30690,6 +30990,12 @@ public override CSharpSyntaxNode VisitArrayRankSpecifier(ArrayRankSpecifierSynta
public override CSharpSyntaxNode VisitPointerType(PointerTypeSyntax node)
=> node.Update((TypeSyntax)Visit(node.ElementType), (SyntaxToken)Visit(node.AsteriskToken));
+ public override CSharpSyntaxNode VisitFunctionPointerType(FunctionPointerTypeSyntax node)
+ => node.Update((SyntaxToken)Visit(node.DelegateKeyword), (SyntaxToken)Visit(node.AsteriskToken), (SyntaxToken)Visit(node.CallingConvention), (SyntaxToken)Visit(node.LessThanToken), VisitList(node.Arguments), (SyntaxToken)Visit(node.GreaterThanToken));
+
+ public override CSharpSyntaxNode VisitModifiedType(ModifiedType node)
+ => node.Update(VisitList(node.Modifiers), (TypeSyntax)Visit(node.Type));
+
public override CSharpSyntaxNode VisitNullableType(NullableTypeSyntax node)
=> node.Update((TypeSyntax)Visit(node.ElementType), (SyntaxToken)Visit(node.QuestionToken));
@@ -31529,6 +31835,41 @@ public PointerTypeSyntax PointerType(TypeSyntax elementType, SyntaxToken asteris
return result;
}
+ public FunctionPointerTypeSyntax FunctionPointerType(SyntaxToken delegateKeyword, SyntaxToken asteriskToken, SyntaxToken? callingConvention, SyntaxToken lessThanToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList arguments, SyntaxToken greaterThanToken)
+ {
+ #if DEBUG
+ if (delegateKeyword == null) throw new ArgumentNullException(nameof(delegateKeyword));
+ if (delegateKeyword.Kind != SyntaxKind.DelegateKeyword) throw new ArgumentException(nameof(delegateKeyword));
+ if (asteriskToken == null) throw new ArgumentNullException(nameof(asteriskToken));
+ if (asteriskToken.Kind != SyntaxKind.AsteriskToken) throw new ArgumentException(nameof(asteriskToken));
+ if (lessThanToken == null) throw new ArgumentNullException(nameof(lessThanToken));
+ if (lessThanToken.Kind != SyntaxKind.LessThanToken) throw new ArgumentException(nameof(lessThanToken));
+ if (greaterThanToken == null) throw new ArgumentNullException(nameof(greaterThanToken));
+ if (greaterThanToken.Kind != SyntaxKind.GreaterThanToken) throw new ArgumentException(nameof(greaterThanToken));
+ #endif
+
+ return new FunctionPointerTypeSyntax(SyntaxKind.FunctionPointerType, delegateKeyword, asteriskToken, callingConvention, lessThanToken, arguments.Node, greaterThanToken, this.context);
+ }
+
+ public ModifiedType ModifiedType(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList modifiers, TypeSyntax type)
+ {
+ #if DEBUG
+ if (type == null) throw new ArgumentNullException(nameof(type));
+ #endif
+
+ int hash;
+ var cached = CSharpSyntaxNodeCache.TryGetNode((int)SyntaxKind.ModifiedType, modifiers.Node, type, this.context, out hash);
+ if (cached != null) return (ModifiedType)cached;
+
+ var result = new ModifiedType(SyntaxKind.ModifiedType, modifiers.Node, type, this.context);
+ if (hash >= 0)
+ {
+ SyntaxNodeCache.AddNode(result, hash);
+ }
+
+ return result;
+ }
+
public NullableTypeSyntax NullableType(TypeSyntax elementType, SyntaxToken questionToken)
{
#if DEBUG
@@ -36093,6 +36434,41 @@ public static PointerTypeSyntax PointerType(TypeSyntax elementType, SyntaxToken
return result;
}
+ public static FunctionPointerTypeSyntax FunctionPointerType(SyntaxToken delegateKeyword, SyntaxToken asteriskToken, SyntaxToken? callingConvention, SyntaxToken lessThanToken, Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList arguments, SyntaxToken greaterThanToken)
+ {
+ #if DEBUG
+ if (delegateKeyword == null) throw new ArgumentNullException(nameof(delegateKeyword));
+ if (delegateKeyword.Kind != SyntaxKind.DelegateKeyword) throw new ArgumentException(nameof(delegateKeyword));
+ if (asteriskToken == null) throw new ArgumentNullException(nameof(asteriskToken));
+ if (asteriskToken.Kind != SyntaxKind.AsteriskToken) throw new ArgumentException(nameof(asteriskToken));
+ if (lessThanToken == null) throw new ArgumentNullException(nameof(lessThanToken));
+ if (lessThanToken.Kind != SyntaxKind.LessThanToken) throw new ArgumentException(nameof(lessThanToken));
+ if (greaterThanToken == null) throw new ArgumentNullException(nameof(greaterThanToken));
+ if (greaterThanToken.Kind != SyntaxKind.GreaterThanToken) throw new ArgumentException(nameof(greaterThanToken));
+ #endif
+
+ return new FunctionPointerTypeSyntax(SyntaxKind.FunctionPointerType, delegateKeyword, asteriskToken, callingConvention, lessThanToken, arguments.Node, greaterThanToken);
+ }
+
+ public static ModifiedType ModifiedType(Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList modifiers, TypeSyntax type)
+ {
+ #if DEBUG
+ if (type == null) throw new ArgumentNullException(nameof(type));
+ #endif
+
+ int hash;
+ var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.ModifiedType, modifiers.Node, type, out hash);
+ if (cached != null) return (ModifiedType)cached;
+
+ var result = new ModifiedType(SyntaxKind.ModifiedType, modifiers.Node, type);
+ if (hash >= 0)
+ {
+ SyntaxNodeCache.AddNode(result, hash);
+ }
+
+ return result;
+ }
+
public static NullableTypeSyntax NullableType(TypeSyntax elementType, SyntaxToken questionToken)
{
#if DEBUG
@@ -40453,6 +40829,8 @@ internal static IEnumerable GetNodeTypes()
typeof(ArrayTypeSyntax),
typeof(ArrayRankSpecifierSyntax),
typeof(PointerTypeSyntax),
+ typeof(FunctionPointerTypeSyntax),
+ typeof(ModifiedType),
typeof(NullableTypeSyntax),
typeof(TupleTypeSyntax),
typeof(TupleElementSyntax),
diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs
index 558faab8b24ae..cf99075f34b22 100644
--- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Main.Generated.cs
@@ -40,6 +40,12 @@ public partial class CSharpSyntaxVisitor
/// Called when the visitor visits a PointerTypeSyntax node.
public virtual TResult VisitPointerType(PointerTypeSyntax node) => this.DefaultVisit(node);
+ /// Called when the visitor visits a FunctionPointerTypeSyntax node.
+ public virtual TResult VisitFunctionPointerType(FunctionPointerTypeSyntax node) => this.DefaultVisit(node);
+
+ /// Called when the visitor visits a ModifiedType node.
+ public virtual TResult VisitModifiedType(ModifiedType node) => this.DefaultVisit(node);
+
/// Called when the visitor visits a NullableTypeSyntax node.
public virtual TResult VisitNullableType(NullableTypeSyntax node) => this.DefaultVisit(node);
@@ -688,6 +694,12 @@ public partial class CSharpSyntaxVisitor
/// Called when the visitor visits a PointerTypeSyntax node.
public virtual void VisitPointerType(PointerTypeSyntax node) => this.DefaultVisit(node);
+ /// Called when the visitor visits a FunctionPointerTypeSyntax node.
+ public virtual void VisitFunctionPointerType(FunctionPointerTypeSyntax node) => this.DefaultVisit(node);
+
+ /// Called when the visitor visits a ModifiedType node.
+ public virtual void VisitModifiedType(ModifiedType node) => this.DefaultVisit(node);
+
/// Called when the visitor visits a NullableTypeSyntax node.
public virtual void VisitNullableType(NullableTypeSyntax node) => this.DefaultVisit(node);
@@ -1336,6 +1348,12 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor
public override SyntaxNode? VisitPointerType(PointerTypeSyntax node)
=> node.Update((TypeSyntax?)Visit(node.ElementType) ?? throw new ArgumentNullException("elementType"), VisitToken(node.AsteriskToken));
+ public override SyntaxNode? VisitFunctionPointerType(FunctionPointerTypeSyntax node)
+ => node.Update(VisitToken(node.DelegateKeyword), VisitToken(node.AsteriskToken), VisitToken(node.CallingConvention), VisitToken(node.LessThanToken), VisitList(node.Arguments), VisitToken(node.GreaterThanToken));
+
+ public override SyntaxNode? VisitModifiedType(ModifiedType node)
+ => node.Update(VisitList(node.Modifiers), (TypeSyntax?)Visit(node.Type) ?? throw new ArgumentNullException("type"));
+
public override SyntaxNode? VisitNullableType(NullableTypeSyntax node)
=> node.Update((TypeSyntax?)Visit(node.ElementType) ?? throw new ArgumentNullException("elementType"), VisitToken(node.QuestionToken));
@@ -2088,6 +2106,35 @@ public static PointerTypeSyntax PointerType(TypeSyntax elementType, SyntaxToken
public static PointerTypeSyntax PointerType(TypeSyntax elementType)
=> SyntaxFactory.PointerType(elementType, SyntaxFactory.Token(SyntaxKind.AsteriskToken));
+ /// Creates a new FunctionPointerTypeSyntax instance.
+ public static FunctionPointerTypeSyntax FunctionPointerType(SyntaxToken delegateKeyword, SyntaxToken asteriskToken, SyntaxToken callingConvention, SyntaxToken lessThanToken, SeparatedSyntaxList arguments, SyntaxToken greaterThanToken)
+ {
+ if (delegateKeyword.Kind() != SyntaxKind.DelegateKeyword) throw new ArgumentException(nameof(delegateKeyword));
+ if (asteriskToken.Kind() != SyntaxKind.AsteriskToken) throw new ArgumentException(nameof(asteriskToken));
+ if (lessThanToken.Kind() != SyntaxKind.LessThanToken) throw new ArgumentException(nameof(lessThanToken));
+ if (greaterThanToken.Kind() != SyntaxKind.GreaterThanToken) throw new ArgumentException(nameof(greaterThanToken));
+ return (FunctionPointerTypeSyntax)Syntax.InternalSyntax.SyntaxFactory.FunctionPointerType((Syntax.InternalSyntax.SyntaxToken)delegateKeyword.Node!, (Syntax.InternalSyntax.SyntaxToken)asteriskToken.Node!, (Syntax.InternalSyntax.SyntaxToken?)callingConvention.Node, (Syntax.InternalSyntax.SyntaxToken)lessThanToken.Node!, arguments.Node.ToGreenSeparatedList(), (Syntax.InternalSyntax.SyntaxToken)greaterThanToken.Node!).CreateRed();
+ }
+
+ /// Creates a new FunctionPointerTypeSyntax instance.
+ public static FunctionPointerTypeSyntax FunctionPointerType(SyntaxToken callingConvention, SeparatedSyntaxList arguments)
+ => SyntaxFactory.FunctionPointerType(SyntaxFactory.Token(SyntaxKind.DelegateKeyword), SyntaxFactory.Token(SyntaxKind.AsteriskToken), callingConvention, SyntaxFactory.Token(SyntaxKind.LessThanToken), arguments, SyntaxFactory.Token(SyntaxKind.GreaterThanToken));
+
+ /// Creates a new FunctionPointerTypeSyntax instance.
+ public static FunctionPointerTypeSyntax FunctionPointerType(SeparatedSyntaxList arguments = default)
+ => SyntaxFactory.FunctionPointerType(SyntaxFactory.Token(SyntaxKind.DelegateKeyword), SyntaxFactory.Token(SyntaxKind.AsteriskToken), default, SyntaxFactory.Token(SyntaxKind.LessThanToken), arguments, SyntaxFactory.Token(SyntaxKind.GreaterThanToken));
+
+ /// Creates a new ModifiedType instance.
+ public static ModifiedType ModifiedType(SyntaxTokenList modifiers, TypeSyntax type)
+ {
+ if (type == null) throw new ArgumentNullException(nameof(type));
+ return (ModifiedType)Syntax.InternalSyntax.SyntaxFactory.ModifiedType(modifiers.Node.ToGreenList(), (Syntax.InternalSyntax.TypeSyntax)type.Green).CreateRed();
+ }
+
+ /// Creates a new ModifiedType instance.
+ public static ModifiedType ModifiedType(TypeSyntax type)
+ => SyntaxFactory.ModifiedType(default(SyntaxTokenList), type);
+
/// Creates a new NullableTypeSyntax instance.
public static NullableTypeSyntax NullableType(TypeSyntax elementType, SyntaxToken questionToken)
{
diff --git a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs
index 1784ddc5423be..2aa55bf71401e 100644
--- a/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/Syntax.xml.Syntax.Generated.cs
@@ -455,6 +455,123 @@ public PointerTypeSyntax Update(TypeSyntax elementType, SyntaxToken asteriskToke
public PointerTypeSyntax WithAsteriskToken(SyntaxToken asteriskToken) => Update(this.ElementType, asteriskToken);
}
+ public sealed partial class FunctionPointerTypeSyntax : TypeSyntax
+ {
+ private SyntaxNode? arguments;
+
+ internal FunctionPointerTypeSyntax(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)
+ : base(green, parent, position)
+ {
+ }
+
+ /// SyntaxToken representing the delegate keyword.
+ public SyntaxToken DelegateKeyword => new SyntaxToken(this, ((Syntax.InternalSyntax.FunctionPointerTypeSyntax)this.Green).delegateKeyword, Position, 0);
+
+ /// SyntaxToken representing the asterisk.
+ public SyntaxToken AsteriskToken => new SyntaxToken(this, ((Syntax.InternalSyntax.FunctionPointerTypeSyntax)this.Green).asteriskToken, GetChildPosition(1), GetChildIndex(1));
+
+ /// SyntaxToken representing the optional calling convention.
+ public SyntaxToken CallingConvention
+ {
+ get
+ {
+ var slot = ((Syntax.InternalSyntax.FunctionPointerTypeSyntax)this.Green).callingConvention;
+ return slot != null ? new SyntaxToken(this, slot, GetChildPosition(2), GetChildIndex(2)) : default;
+ }
+ }
+
+ /// SyntaxToken representing the less than token.
+ public SyntaxToken LessThanToken => new SyntaxToken(this, ((Syntax.InternalSyntax.FunctionPointerTypeSyntax)this.Green).lessThanToken, GetChildPosition(3), GetChildIndex(3));
+
+ /// SeparatedSyntaxList of ModifiedTypes representing the list of parameters and return type.
+ public SeparatedSyntaxList Arguments
+ {
+ get
+ {
+ var red = GetRed(ref this.arguments, 4);
+ return red != null ? new SeparatedSyntaxList(red, GetChildIndex(4)) : default;
+ }
+ }
+
+ /// SyntaxToken representing the greater than token.
+ public SyntaxToken GreaterThanToken => new SyntaxToken(this, ((Syntax.InternalSyntax.FunctionPointerTypeSyntax)this.Green).greaterThanToken, GetChildPosition(5), GetChildIndex(5));
+
+ internal override SyntaxNode? GetNodeSlot(int index) => index == 4 ? GetRed(ref this.arguments, 4)! : null;
+
+ internal override SyntaxNode? GetCachedSlot(int index) => index == 4 ? this.arguments : null;
+
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitFunctionPointerType(this);
+ public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitFunctionPointerType(this);
+
+ public FunctionPointerTypeSyntax Update(SyntaxToken delegateKeyword, SyntaxToken asteriskToken, SyntaxToken callingConvention, SyntaxToken lessThanToken, SeparatedSyntaxList arguments, SyntaxToken greaterThanToken)
+ {
+ if (delegateKeyword != this.DelegateKeyword || asteriskToken != this.AsteriskToken || callingConvention != this.CallingConvention || lessThanToken != this.LessThanToken || arguments != this.Arguments || greaterThanToken != this.GreaterThanToken)
+ {
+ var newNode = SyntaxFactory.FunctionPointerType(delegateKeyword, asteriskToken, callingConvention, lessThanToken, arguments, greaterThanToken);
+ var annotations = GetAnnotations();
+ return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode;
+ }
+
+ return this;
+ }
+
+ public FunctionPointerTypeSyntax WithDelegateKeyword(SyntaxToken delegateKeyword) => Update(delegateKeyword, this.AsteriskToken, this.CallingConvention, this.LessThanToken, this.Arguments, this.GreaterThanToken);
+ public FunctionPointerTypeSyntax WithAsteriskToken(SyntaxToken asteriskToken) => Update(this.DelegateKeyword, asteriskToken, this.CallingConvention, this.LessThanToken, this.Arguments, this.GreaterThanToken);
+ public FunctionPointerTypeSyntax WithCallingConvention(SyntaxToken callingConvention) => Update(this.DelegateKeyword, this.AsteriskToken, callingConvention, this.LessThanToken, this.Arguments, this.GreaterThanToken);
+ public FunctionPointerTypeSyntax WithLessThanToken(SyntaxToken lessThanToken) => Update(this.DelegateKeyword, this.AsteriskToken, this.CallingConvention, lessThanToken, this.Arguments, this.GreaterThanToken);
+ public FunctionPointerTypeSyntax WithArguments(SeparatedSyntaxList arguments) => Update(this.DelegateKeyword, this.AsteriskToken, this.CallingConvention, this.LessThanToken, arguments, this.GreaterThanToken);
+ public FunctionPointerTypeSyntax WithGreaterThanToken(SyntaxToken greaterThanToken) => Update(this.DelegateKeyword, this.AsteriskToken, this.CallingConvention, this.LessThanToken, this.Arguments, greaterThanToken);
+
+ public FunctionPointerTypeSyntax AddArguments(params ModifiedType[] items) => WithArguments(this.Arguments.AddRange(items));
+ }
+
+ public sealed partial class ModifiedType : CSharpSyntaxNode
+ {
+ private TypeSyntax? type;
+
+ internal ModifiedType(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)
+ : base(green, parent, position)
+ {
+ }
+
+ /// SyntaxList of the optional modifier keywords.
+ public SyntaxTokenList Modifiers
+ {
+ get
+ {
+ var slot = this.Green.GetSlot(0);
+ return slot != null ? new SyntaxTokenList(this, slot, Position, 0) : default;
+ }
+ }
+
+ /// TypeSyntax representing the modified type.
+ public TypeSyntax Type => GetRed(ref this.type, 1)!;
+
+ internal override SyntaxNode? GetNodeSlot(int index) => index == 1 ? GetRed(ref this.type, 1)! : null;
+
+ internal override SyntaxNode? GetCachedSlot(int index) => index == 1 ? this.type : null;
+
+ public override void Accept(CSharpSyntaxVisitor visitor) => visitor.VisitModifiedType(this);
+ public override TResult Accept(CSharpSyntaxVisitor visitor) => visitor.VisitModifiedType(this);
+
+ public ModifiedType Update(SyntaxTokenList modifiers, TypeSyntax type)
+ {
+ if (modifiers != this.Modifiers || type != this.Type)
+ {
+ var newNode = SyntaxFactory.ModifiedType(modifiers, type);
+ var annotations = GetAnnotations();
+ return annotations?.Length > 0 ? newNode.WithAnnotations(annotations) : newNode;
+ }
+
+ return this;
+ }
+
+ public ModifiedType WithModifiers(SyntaxTokenList modifiers) => Update(modifiers, this.Type);
+ public ModifiedType WithType(TypeSyntax type) => Update(this.Modifiers, type);
+
+ public ModifiedType AddModifiers(params SyntaxToken[] items) => WithModifiers(this.Modifiers.AddRange(items));
+ }
+
/// Class which represents the syntax node for a nullable type.
public sealed partial class NullableTypeSyntax : TypeSyntax
{
diff --git a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs
index 0e52e4c28a740..7dc92280f15ce 100644
--- a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs
+++ b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs
@@ -32,4 +32,4 @@
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(System.String,Microsoft.CodeAnalysis.CSharp.CSharpParseOptions,System.String,System.Text.Encoding,System.Collections.Immutable.ImmutableDictionary{System.String,Microsoft.CodeAnalysis.ReportDiagnostic},System.Threading.CancellationToken)~Microsoft.CodeAnalysis.SyntaxTree")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(Microsoft.CodeAnalysis.Text.SourceText,Microsoft.CodeAnalysis.CSharp.CSharpParseOptions,System.String,System.Collections.Immutable.ImmutableDictionary{System.String,Microsoft.CodeAnalysis.ReportDiagnostic},System.Threading.CancellationToken)~Microsoft.CodeAnalysis.SyntaxTree")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.DeconstructionPatternClause(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.SubpatternSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.DeconstructionPatternClauseSyntax")]
-
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FunctionPointerType(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType})~Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax")]
diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
index a723f71b6ace7..a401d1e39067a 100644
--- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
+++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
@@ -77,9 +77,11 @@ internal enum TerminatorState
IsEndOfTypeParameterList = 1 << 20,
IsEndOfMethodSignature = 1 << 21,
IsEndOfNameInExplicitInterface = 1 << 22,
+ IsEndOfFunctionPointerParameterList = 1 << 23,
+ IsEndOfFunctionPointerParameterListErrored = 1 << 24,
}
- private const int LastTerminatorState = (int)TerminatorState.IsEndOfNameInExplicitInterface;
+ private const int LastTerminatorState = (int)TerminatorState.IsEndOfFunctionPointerParameterListErrored;
private bool IsTerminator()
{
@@ -115,6 +117,8 @@ private bool IsTerminator()
case TerminatorState.IsEndOfTypeParameterList when this.IsEndOfTypeParameterList():
case TerminatorState.IsEndOfMethodSignature when this.IsEndOfMethodSignature():
case TerminatorState.IsEndOfNameInExplicitInterface when this.IsEndOfNameInExplicitInterface():
+ case TerminatorState.IsEndOfFunctionPointerParameterList when this.IsEndOfFunctionPointerParameterList(errored: false):
+ case TerminatorState.IsEndOfFunctionPointerParameterListErrored when this.IsEndOfFunctionPointerParameterList(errored: true):
return true;
}
}
@@ -1857,7 +1861,7 @@ private bool IsTypeDeclarationStart()
switch (this.CurrentToken.Kind)
{
case SyntaxKind.ClassKeyword:
- case SyntaxKind.DelegateKeyword:
+ case SyntaxKind.DelegateKeyword when !IsFunctionPointerStart():
case SyntaxKind.EnumKeyword:
case SyntaxKind.InterfaceKeyword:
case SyntaxKind.StructKeyword:
@@ -2533,6 +2537,8 @@ private bool IsEndOfNameInExplicitInterface()
return this.CurrentToken.Kind == SyntaxKind.DotToken || this.CurrentToken.Kind == SyntaxKind.ColonColonToken;
}
+ private bool IsEndOfFunctionPointerParameterList(bool errored) => this.CurrentToken.Kind == (errored ? SyntaxKind.CloseParenToken : SyntaxKind.GreaterThanToken);
+
private MethodDeclarationSyntax ParseMethodDeclaration(
SyntaxList attributes,
SyntaxListBuilder modifiers,
@@ -3547,6 +3553,7 @@ private bool IsPossibleParameter()
case SyntaxKind.OpenBracketToken: // attribute
case SyntaxKind.ArgListKeyword:
case SyntaxKind.OpenParenToken: // tuple
+ case SyntaxKind.DelegateKeyword when IsFunctionPointerStart(): // Function pointer type
return true;
case SyntaxKind.IdentifierToken:
@@ -3646,7 +3653,7 @@ private ParameterSyntax ParseParameter()
}
}
- private static bool IsParameterModifier(SyntaxKind kind)
+ private static bool IsParameterModifier(SyntaxKind kind, bool isFunctionPointerParameter = false)
{
switch (kind)
{
@@ -3655,15 +3662,16 @@ private static bool IsParameterModifier(SyntaxKind kind)
case SyntaxKind.OutKeyword:
case SyntaxKind.InKeyword:
case SyntaxKind.ParamsKeyword:
+ case SyntaxKind.ReadOnlyKeyword when isFunctionPointerParameter:
return true;
}
return false;
}
- private void ParseParameterModifiers(SyntaxListBuilder modifiers)
+ private void ParseParameterModifiers(SyntaxListBuilder modifiers, bool isFunctionPointerParameter = false)
{
- while (IsParameterModifier(this.CurrentToken.Kind))
+ while (IsParameterModifier(this.CurrentToken.Kind, isFunctionPointerParameter))
{
var modifier = this.EatToken();
@@ -5605,7 +5613,9 @@ private enum ScanTypeFlags
///
/// Definitely a type name: either a predefined type (int, string, etc.) or an array
- /// type (ending with a [] brackets), or a pointer type (ending with *s).
+ /// type (ending with a [] brackets), or a pointer type (ending with *s), or a function
+ /// pointer type (ending with > in valid cases, or a *, ), or calling convention
+ /// identifier, in invalid cases).
///
MustBeType,
@@ -5751,6 +5761,10 @@ private ScanTypeFlags ScanType(ParseTypeMode mode, out SyntaxToken lastTokenOfTy
return ScanTypeFlags.NotType;
}
}
+ else if (IsFunctionPointerStart())
+ {
+ return ScanFunctionPointerType(out lastTokenOfType);
+ }
else
{
// Can't be a type!
@@ -5874,6 +5888,83 @@ private ScanTypeFlags ScanTupleType(out SyntaxToken lastTokenOfType)
return ScanTypeFlags.NotType;
}
+#nullable enable
+ private ScanTypeFlags ScanFunctionPointerType(out SyntaxToken lastTokenOfType)
+ {
+ Debug.Assert(IsFunctionPointerStart());
+ _ = EatToken(SyntaxKind.DelegateKeyword);
+ lastTokenOfType = EatToken(SyntaxKind.AsteriskToken);
+
+ if (IsPossibleCallingConvention(lastTokenOfType))
+ {
+ lastTokenOfType = EatToken();
+ }
+
+ if (!IsPossibleFunctionPointerParameterListStart(CurrentToken))
+ {
+ // Even though this function pointer type is incomplete, we know that it
+ // must be the start of a type, as there is no other possible interpretation
+ // of delegate*. By always treating it as a type, we ensure that any disambiguation
+ // done in later parsing treats this as a type, which will produce better
+ // errors at later stages.
+ return ScanTypeFlags.MustBeType;
+ }
+
+ var validStartingToken = EatToken().Kind == SyntaxKind.LessThanToken;
+
+ var saveTerm = _termState;
+ _termState |= validStartingToken ? TerminatorState.IsEndOfFunctionPointerParameterList : TerminatorState.IsEndOfFunctionPointerParameterListErrored;
+
+ try
+ {
+ do
+ {
+ var ignoredModifiers = _pool.Allocate();
+ try
+ {
+ ParseParameterModifiers(ignoredModifiers, isFunctionPointerParameter: true);
+ }
+ finally
+ {
+ _pool.Free(ignoredModifiers);
+ }
+
+ _ = ScanType(out _);
+
+ if (skipBadFunctionPointerParameterTokens() == PostSkipAction.Abort)
+ {
+ break;
+ }
+
+ _ = EatToken(SyntaxKind.CommaToken);
+ }
+ while (true);
+ }
+ finally
+ {
+ _termState = saveTerm;
+ }
+
+ if (!validStartingToken && CurrentToken.Kind == SyntaxKind.CloseParenToken)
+ {
+ lastTokenOfType = EatTokenAsKind(SyntaxKind.GreaterThanToken);
+ }
+ else
+ {
+ lastTokenOfType = EatToken(SyntaxKind.GreaterThanToken);
+ }
+
+ return ScanTypeFlags.MustBeType;
+
+ PostSkipAction skipBadFunctionPointerParameterTokens()
+ {
+ return SkipBadTokensWithExpectedKind(isNotExpectedFunction: p => p.CurrentToken.Kind != SyntaxKind.CommaToken,
+ abortFunction: p => p.IsTerminator(),
+ expected: SyntaxKind.CommaToken, trailingTrivia: out _);
+ }
+ }
+#nullable restore
+
private static bool IsPredefinedType(SyntaxKind keyword)
{
return SyntaxFacts.IsPredefinedType(keyword);
@@ -5905,7 +5996,7 @@ private enum ParseTypeMode
AfterTupleComma,
AsExpression,
NewExpression,
- FirstElementOfPossibleTupleLiteral
+ FirstElementOfPossibleTupleLiteral,
}
private TypeSyntax ParseType(ParseTypeMode mode = ParseTypeMode.Normal)
@@ -6266,6 +6357,10 @@ private TypeSyntax ParseUnderlyingType(bool parentIsParameter, NameOptions optio
{
return this.ParseTupleType();
}
+ else if (IsFunctionPointerStart())
+ {
+ return ParseFunctionPointerTypeSyntax();
+ }
else
{
var name = this.CreateMissingIdentifierName();
@@ -6273,6 +6368,164 @@ private TypeSyntax ParseUnderlyingType(bool parentIsParameter, NameOptions optio
}
}
+#nullable enable
+ private FunctionPointerTypeSyntax ParseFunctionPointerTypeSyntax()
+ {
+ Debug.Assert(IsFunctionPointerStart());
+ var @delegate = EatToken(SyntaxKind.DelegateKeyword);
+ var asterisk = EatToken(SyntaxKind.AsteriskToken);
+ // Invalid calling conventions will be reported at type binding time
+ var callingConvention = IsPossibleCallingConvention(asterisk) ? EatToken() : null;
+
+ if (!IsPossibleFunctionPointerParameterListStart(CurrentToken))
+ {
+ var lessThanTokenError = WithAdditionalDiagnostics(SyntaxFactory.MissingToken(SyntaxKind.LessThanToken), GetExpectedTokenError(SyntaxKind.LessThanToken, SyntaxKind.None));
+ var missingTypes = _pool.AllocateSeparated();
+ var missingTypeName = CreateMissingIdentifierName();
+ var missingType = SyntaxFactory.ModifiedType(default, missingTypeName);
+ missingTypes.Add(missingType);
+ // Handle the simple case of delegate*>. We don't try to deal with any variation of delegate*invalid>, as
+ // we don't know for sure that the expression isn't a relational with something else.
+ var greaterThanTokenError = TryEatToken(SyntaxKind.GreaterThanToken) ?? SyntaxFactory.MissingToken(SyntaxKind.GreaterThanToken);
+
+ var funcPtr = SyntaxFactory.FunctionPointerType(@delegate, asterisk, callingConvention, lessThanTokenError, missingTypes, greaterThanTokenError);
+ _pool.Free(missingTypes);
+ return funcPtr;
+ }
+
+ var lessThanToken = EatTokenAsKind(SyntaxKind.LessThanToken);
+ var saveTerm = _termState;
+ _termState |= (lessThanToken.IsMissing ? TerminatorState.IsEndOfFunctionPointerParameterListErrored : TerminatorState.IsEndOfFunctionPointerParameterList);
+ var types = _pool.AllocateSeparated();
+
+ try
+ {
+ while (true)
+ {
+ var modifiers = _pool.Allocate();
+ try
+ {
+ ParseParameterModifiers(modifiers, isFunctionPointerParameter: true);
+
+ var parameterType = ParseTypeOrVoid();
+ types.Add(SyntaxFactory.ModifiedType(modifiers, parameterType));
+
+ if (skipBadFunctionPointerParameterListTokens() == PostSkipAction.Abort)
+ {
+ break;
+ }
+
+ Debug.Assert(CurrentToken.Kind == SyntaxKind.CommaToken);
+ types.AddSeparator(EatToken(SyntaxKind.CommaToken));
+ }
+ finally
+ {
+ _pool.Free(modifiers);
+ }
+ }
+
+ SyntaxToken greaterThanToken;
+ if (lessThanToken.IsMissing && CurrentToken.Kind == SyntaxKind.CloseParenToken)
+ {
+ greaterThanToken = EatTokenAsKind(SyntaxKind.GreaterThanToken);
+ }
+ else
+ {
+ greaterThanToken = EatToken(SyntaxKind.GreaterThanToken);
+ }
+
+ var funcPointer = SyntaxFactory.FunctionPointerType(@delegate, asterisk, callingConvention, lessThanToken, types, greaterThanToken);
+ funcPointer = CheckFeatureAvailability(funcPointer, MessageID.IDS_FeatureFunctionPointers);
+ return funcPointer;
+ }
+ finally
+ {
+ _termState = saveTerm;
+ _pool.Free(types);
+ }
+
+ PostSkipAction skipBadFunctionPointerParameterListTokens()
+ {
+ CSharpSyntaxNode? tmp = null;
+ Debug.Assert(types.Count > 0);
+ return SkipBadSeparatedListTokensWithExpectedKind(ref tmp,
+ types,
+ isNotExpectedFunction: p => p.CurrentToken.Kind != SyntaxKind.CommaToken,
+ abortFunction: p => p.IsTerminator(),
+ expected: SyntaxKind.CommaToken);
+ }
+ }
+
+ private bool IsFunctionPointerStart()
+ => CurrentToken.Kind == SyntaxKind.DelegateKeyword && PeekToken(1).Kind == SyntaxKind.AsteriskToken;
+
+ private bool IsPossibleCallingConvention(SyntaxToken asteriskToken)
+ {
+ if (IsPossibleFunctionPointerParameterListStart(CurrentToken))
+ {
+ return false;
+ }
+
+ // If the next token is a known function pointer calling convention, treat it as a
+ // calling convention no matter what. If it wasn't intended to be a calling convention
+ // we'd have an error anyway, and it's more likely the user intended for it to be a
+ // function pointer convention than not.
+ // PROTOTYPE(func-ptr): refactor this out into a helper method to share with binding
+ switch (CurrentToken.Text)
+ {
+ case "cdecl":
+ case "managed":
+ case "unmanaged":
+ case "thiscall":
+ case "stdcall":
+ return true;
+ }
+
+ // For nicer error recovery, we only treat predefined types and identifiers as if they could be the
+ // calling convention. For any other keyword, they're almost certainly part of some other
+ // construct, and would produce better errors if parsed separately. The user could have this:
+ //
+ // delegate* /* Declaration in progress */ while (true) {}
+ //
+ // The parse tree will look much better if the while(true) is considered a separate structure,
+ // even though it does look like it could be the start of an invalid function pointer definition.
+ if (CurrentToken.Kind != SyntaxKind.IdentifierToken && !IsPredefinedType(CurrentToken.Kind))
+ {
+ return false;
+ }
+
+ // If the asterisk was at the end of the previous line and it's not a valid calling convention,
+ // chances are anything on a new line should not be considered part of the function pointer.
+ // For example:
+ //
+ // delegate*
+ // int myValue = 1;
+ //
+ // would be better interpreted if the int myValue = 1 is considered separately
+ if (asteriskToken.TrailingTrivia.Any((int)SyntaxKind.EndOfLineTrivia))
+ {
+ return false;
+ }
+
+ // We attempt to make error recovery a little nicer here by only treating a single
+ // identifier token as a calling convention if the token afterwards is actually a
+ // possible start to the function pointer parameter list. The intuition is that, for
+ // some partial trees like this:
+ //
+ // (delegate*MyProperty.MyMethod();
+ //
+ // The user is actually in the middle of adding a cast, and if we interpreted MyProperty
+ // as a calling convention, we'd get a much worse set of errors than if we treated the
+ // function pointer as having no calling convention.
+ return IsPossibleFunctionPointerParameterListStart(PeekToken(1));
+ }
+
+ private static bool IsPossibleFunctionPointerParameterListStart(SyntaxToken token)
+ // We consider both ( and < to be possible starts, in order to make error recovery more graceful
+ // in the scenario where a user accidentally surrounds their function pointer type list with parens.
+ => token.Kind == SyntaxKind.LessThanToken || token.Kind == SyntaxKind.OpenParenToken;
+#nullable restore
+
private TypeSyntax ParsePointerTypeMods(TypeSyntax type)
{
// Check for pointer types
@@ -10936,6 +11189,9 @@ private bool IsPossibleLambdaParameter()
case SyntaxKind.IdentifierToken:
return this.IsTrueIdentifier();
+ case SyntaxKind.DelegateKeyword:
+ return this.IsFunctionPointerStart();
+
default:
return IsPredefinedType(this.CurrentToken.Kind);
}
@@ -10994,6 +11250,11 @@ private bool ShouldParseLambdaParameterType(bool hasModifier)
return true;
}
+ if (this.IsFunctionPointerStart())
+ {
+ return true;
+ }
+
if (this.IsTrueIdentifier(this.CurrentToken))
{
// Don't parse out a type if we see:
diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
index 86446aaa8b46e..74ae1616c934d 100644
--- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
+++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
@@ -61,7 +61,7 @@ private CSharpSyntaxNode ParseTypeOrPatternForIsOperatorCore()
}
// If it starts with 'nameof(', skip the 'if' and parse as a constant pattern.
- if (LooksLikeTypeOfPattern(tk))
+ if (LooksLikeTypeOfPattern())
{
var resetPoint = this.GetResetPoint();
try
@@ -126,12 +126,32 @@ private CSharpSyntaxNode ParseTypeOrPatternForIsOperatorCore()
///
/// Given tk, the type of the current token, does this look like the type of a pattern?
///
- private bool LooksLikeTypeOfPattern(SyntaxKind tk)
+ private bool LooksLikeTypeOfPattern()
{
- return SyntaxFacts.IsPredefinedType(tk) ||
- (tk == SyntaxKind.IdentifierToken && this.CurrentToken.ContextualKind != SyntaxKind.UnderscoreToken &&
- (this.CurrentToken.ContextualKind != SyntaxKind.NameOfKeyword || this.PeekToken(1).Kind != SyntaxKind.OpenParenToken)) ||
- LooksLikeTupleArrayType();
+ var tk = CurrentToken.Kind;
+ if (SyntaxFacts.IsPredefinedType(tk))
+ {
+ return true;
+ }
+
+ if (tk == SyntaxKind.IdentifierToken && this.CurrentToken.ContextualKind != SyntaxKind.UnderscoreToken &&
+ (this.CurrentToken.ContextualKind != SyntaxKind.NameOfKeyword || this.PeekToken(1).Kind != SyntaxKind.OpenParenToken))
+ {
+ return true;
+ }
+
+ if (LooksLikeTupleArrayType())
+ {
+ return true;
+ }
+
+ // We'll parse the function pointer, but issue an error in semantic analysis
+ if (IsFunctionPointerStart())
+ {
+ return true;
+ }
+
+ return false;
}
//
@@ -347,7 +367,7 @@ private CSharpSyntaxNode ParseExpressionOrPattern(bool whenIsKeyword, bool forSw
try
{
TypeSyntax type = null;
- if (LooksLikeTypeOfPattern(tk))
+ if (LooksLikeTypeOfPattern())
{
type = this.ParseType(ParseTypeMode.DefinitePattern);
if (type.IsMissing || !CanTokenFollowTypeInPattern())
diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
index 2e7319a75691c..2ed84d29bb858 100644
--- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
+++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
@@ -11,9 +11,31 @@ Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.WithBlock
Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.WithExpressionBody(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken asyncKeyword, Microsoft.CodeAnalysis.SyntaxToken delegateKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax.WithExpressionBody(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.AddArguments(params Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.Arguments.get -> Microsoft.CodeAnalysis.SeparatedSyntaxList
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.AsteriskToken.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.CallingConvention.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.DelegateKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.GreaterThanToken.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.LessThanToken.get -> Microsoft.CodeAnalysis.SyntaxToken
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken delegateKeyword, Microsoft.CodeAnalysis.SyntaxToken asteriskToken, Microsoft.CodeAnalysis.SyntaxToken callingConvention, Microsoft.CodeAnalysis.SyntaxToken lessThanToken, Microsoft.CodeAnalysis.SeparatedSyntaxList arguments, Microsoft.CodeAnalysis.SyntaxToken greaterThanToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.WithArguments(Microsoft.CodeAnalysis.SeparatedSyntaxList arguments) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.WithAsteriskToken(Microsoft.CodeAnalysis.SyntaxToken asteriskToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.WithCallingConvention(Microsoft.CodeAnalysis.SyntaxToken callingConvention) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.WithDelegateKeyword(Microsoft.CodeAnalysis.SyntaxToken delegateKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.WithGreaterThanToken(Microsoft.CodeAnalysis.SyntaxToken greaterThanToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.WithLessThanToken(Microsoft.CodeAnalysis.SyntaxToken lessThanToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LambdaExpressionSyntax.AddBlockStatements(params Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LambdaExpressionSyntax.WithBlock(Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block) -> Microsoft.CodeAnalysis.CSharp.Syntax.LambdaExpressionSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LambdaExpressionSyntax.WithExpressionBody(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.LambdaExpressionSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType
+Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType.AddModifiers(params Microsoft.CodeAnalysis.SyntaxToken[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType
+Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType.Modifiers.get -> Microsoft.CodeAnalysis.SyntaxTokenList
+Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType.Type.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax
+Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType.Update(Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType
+Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType.WithModifiers(Microsoft.CodeAnalysis.SyntaxTokenList modifiers) -> Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType
+Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType.WithType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType
Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.AddBlockStatements(params Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken asyncKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.WithBlock(Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax
@@ -22,18 +44,35 @@ Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.AddBlockStatem
Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken asyncKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax parameter, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.WithBlock(Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.WithExpressionBody(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax
+Microsoft.CodeAnalysis.CSharp.SyntaxKind.ModifiedType = 9057 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
+Microsoft.CodeAnalysis.CSharp.SyntaxKind.FunctionPointerType = 9056 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
abstract Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.Block.get -> Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax
abstract Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousFunctionExpressionSyntax.ExpressionBody.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax
+override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitModifiedType(Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType node) -> Microsoft.CodeAnalysis.SyntaxNode
+override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitFunctionPointerType(Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax node) -> Microsoft.CodeAnalysis.SyntaxNode
override Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax.Block.get -> Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax
override Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax.ExpressionBody.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax
+override Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void
+override Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult
+override Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void
+override Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult
override Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.Block.get -> Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax
override Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax.ExpressionBody.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax
override Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.Block.get -> Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax
override Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.ExpressionBody.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.AnonymousMethodExpression(Microsoft.CodeAnalysis.SyntaxToken asyncKeyword, Microsoft.CodeAnalysis.SyntaxToken delegateKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.AnonymousMethodExpressionSyntax
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FunctionPointerType(Microsoft.CodeAnalysis.SeparatedSyntaxList arguments = default(Microsoft.CodeAnalysis.SeparatedSyntaxList)) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FunctionPointerType(Microsoft.CodeAnalysis.SyntaxToken callingConvention, Microsoft.CodeAnalysis.SeparatedSyntaxList arguments) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FunctionPointerType(Microsoft.CodeAnalysis.SyntaxToken delegateKeyword, Microsoft.CodeAnalysis.SyntaxToken asteriskToken, Microsoft.CodeAnalysis.SyntaxToken callingConvention, Microsoft.CodeAnalysis.SyntaxToken lessThanToken, Microsoft.CodeAnalysis.SeparatedSyntaxList arguments, Microsoft.CodeAnalysis.SyntaxToken greaterThanToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ModifiedType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType
+static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ModifiedType(Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedLambdaExpression() -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedLambdaExpression(Microsoft.CodeAnalysis.SyntaxToken asyncKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedLambdaExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SimpleLambdaExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax parameter) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SimpleLambdaExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax parameter, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SimpleLambdaExpression(Microsoft.CodeAnalysis.SyntaxToken asyncKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterSyntax parameter, Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax block, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax
+virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitModifiedType(Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType node) -> void
+virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitFunctionPointerType(Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax node) -> void
+virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitModifiedType(Microsoft.CodeAnalysis.CSharp.Syntax.ModifiedType node) -> TResult
+virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitFunctionPointerType(Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax node) -> TResult
diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml
index d4589ef67bb79..d94ca4ad852bd 100644
--- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml
+++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml
@@ -223,6 +223,56 @@
Creates a PointerTypeSyntax node.
+
+
+
+
+
+ SyntaxToken representing the delegate keyword.
+
+
+
+
+
+ SyntaxToken representing the asterisk.
+
+
+
+
+ SyntaxToken representing the optional calling convention.
+
+
+
+
+
+ SyntaxToken representing the less than token.
+
+
+
+
+ SeparatedSyntaxList of ModifiedTypes representing the list of parameters and return type.
+
+
+
+
+
+ SyntaxToken representing the greater than token.
+
+
+
+
+
+
+
+ SyntaxList of the optional modifier keywords.
+
+
+
+
+ TypeSyntax representing the modified type.
+
+
+
diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs
index 89b43c01cd782..2c3db69c5487f 100644
--- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs
+++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs
@@ -594,5 +594,7 @@ public enum SyntaxKind : ushort
ImplicitStackAllocArrayCreationExpression = 9053,
SuppressNullableWarningExpression = 9054,
NullableDirectiveTrivia = 9055,
+ FunctionPointerType = 9056,
+ ModifiedType = 9057,
}
}
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
index 301de31075750..91f4d4ecf8ef0 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
Neplatný název algoritmu hash: {0}
@@ -829,6 +834,11 @@
rozšiřitelný příkaz fixed
+
+ function pointers
+ function pointers
+
+
index operator
operátor indexu
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
index efe063d472119..742c246c68b96 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
Ungültiger Name für Hashalgorithmus: "{0}"
@@ -829,6 +834,11 @@
Erweiterbare fixed-Anweisung
+
+ function pointers
+ function pointers
+
+
index operator
Indexoperator
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
index f7c6745971011..8dd22f1316629 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
Nombre de algoritmo hash no válido: "{0}"
@@ -830,6 +835,11 @@
declaración fija extensible
+
+ function pointers
+ function pointers
+
+
index operator
operador de índice
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
index 3f0c495358965..3c8828f7bb123 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
Nom d'algorithme de hachage non valide : '{0}'
@@ -829,6 +834,11 @@
instruction fixed extensible
+
+ function pointers
+ function pointers
+
+
index operator
opérateur d'index
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
index 9ac10140a2bf6..0c74c36970fd1 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
Il nome dell'algoritmo hash non è valido: '{0}'
@@ -829,6 +834,11 @@
istruzione fixed estendibile
+
+ function pointers
+ function pointers
+
+
index operator
operatore di indice
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
index 46a89bde0bd71..697302e111657 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
無効なハッシュ アルゴリズム名: '{0}'
@@ -829,6 +834,11 @@
拡張可能な fixed ステートメント
+
+ function pointers
+ function pointers
+
+
index operator
インデックス演算子
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
index fbad2a17b5450..d69c91f7dc631 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
잘못된 해시 알고리즘 이름: '{0}'
@@ -829,6 +834,11 @@
확장 가능한 fixed 문
+
+ function pointers
+ function pointers
+
+
index operator
인덱스 연산자
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
index 39ffad0032bc7..c7b3647890b63 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
Nieprawidłowa nazwa algorytmu wyznaczania wartości skrótu: „{0}”
@@ -829,6 +834,11 @@
rozszerzalna instrukcja fixed
+
+ function pointers
+ function pointers
+
+
index operator
operator indeksowania
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
index 5c0f011ef540b..a70a00bfacba0 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
Nome de algoritmo de hash inválido: '{0}'
@@ -829,6 +834,11 @@
instrução fixa extensível
+
+ function pointers
+ function pointers
+
+
index operator
operador de índice
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
index 4c525e8eb3307..e09846ab0d1b3 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
Недопустимое имя хэш-алгоритма: "{0}"
@@ -829,6 +834,11 @@
расширяемый оператор fixed
+
+ function pointers
+ function pointers
+
+
index operator
оператор index
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
index 2b88c024f68fe..1164d8d948ab7 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
Geçersiz karma algoritması adı: '{0}'
@@ -829,6 +834,11 @@
genişletilebilir fixed deyimi
+
+ function pointers
+ function pointers
+
+
index operator
dizin işleci
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
index 7503df260c04e..a989dd4dbb78a 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
无效的哈希算法名称:“{0}”
@@ -829,6 +834,11 @@
可扩展 fixed 语句
+
+ function pointers
+ function pointers
+
+
index operator
索引运算符
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
index 31be7fab29761..724e994f1fb11 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
@@ -237,6 +237,11 @@
Internal error in the C# compiler.
+
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+ '{0}' is not a valid calling convention for a function pointer. Valid conventions are 'cdecl', 'managed', 'unmanaged', 'thiscall', and 'stdcall'.
+
+
Invalid hash algorithm name: '{0}'
雜湊演算法名稱無效: '{0}'
@@ -829,6 +834,11 @@
可延伸 fixed 陳述式
+
+ function pointers
+ function pointers
+
+
index operator
索引運算子
diff --git a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs
index 3bbbf1a9ddddd..fccf62a5fb3df 100644
--- a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs
@@ -25,7 +25,12 @@ public void DiagnosticAnalyzerAllInOne()
symbolKindsWithNoCodeBlocks.Add(SymbolKind.Property);
// Add nodes that are not yet in AllInOneCSharpCode to this list.
- var missingSyntaxKinds = new HashSet();
+ var missingSyntaxKinds = new HashSet()
+ {
+ // PROTOYPE(func-ptr): Remove
+ SyntaxKind.FunctionPointerType,
+ SyntaxKind.ModifiedType
+ };
var analyzer = new CSharpTrackingDiagnosticAnalyzer();
CreateCompilationWithMscorlib45(source).VerifyAnalyzerDiagnostics(new[] { analyzer });
diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
index 2c8dc55f4d287..0e4ef8f9abe3a 100644
--- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
@@ -37,6 +37,12 @@ private static Syntax.InternalSyntax.ArrayRankSpecifierSyntax GenerateArrayRankS
private static Syntax.InternalSyntax.PointerTypeSyntax GeneratePointerType()
=> InternalSyntaxFactory.PointerType(GenerateIdentifierName(), InternalSyntaxFactory.Token(SyntaxKind.AsteriskToken));
+ private static Syntax.InternalSyntax.FunctionPointerTypeSyntax GenerateFunctionPointerType()
+ => InternalSyntaxFactory.FunctionPointerType(InternalSyntaxFactory.Token(SyntaxKind.DelegateKeyword), InternalSyntaxFactory.Token(SyntaxKind.AsteriskToken), null, InternalSyntaxFactory.Token(SyntaxKind.LessThanToken), new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SeparatedSyntaxList(), InternalSyntaxFactory.Token(SyntaxKind.GreaterThanToken));
+
+ private static Syntax.InternalSyntax.ModifiedType GenerateModifiedType()
+ => InternalSyntaxFactory.ModifiedType(new Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(), GenerateIdentifierName());
+
private static Syntax.InternalSyntax.NullableTypeSyntax GenerateNullableType()
=> InternalSyntaxFactory.NullableType(GenerateIdentifierName(), InternalSyntaxFactory.Token(SyntaxKind.QuestionToken));
@@ -758,6 +764,32 @@ public void TestPointerTypeFactoryAndProperties()
AttachAndCheckDiagnostics(node);
}
+ [Fact]
+ public void TestFunctionPointerTypeFactoryAndProperties()
+ {
+ var node = GenerateFunctionPointerType();
+
+ Assert.Equal(SyntaxKind.DelegateKeyword, node.DelegateKeyword.Kind);
+ Assert.Equal(SyntaxKind.AsteriskToken, node.AsteriskToken.Kind);
+ Assert.Null(node.CallingConvention);
+ Assert.Equal(SyntaxKind.LessThanToken, node.LessThanToken.Kind);
+ Assert.Equal(default, node.Arguments);
+ Assert.Equal(SyntaxKind.GreaterThanToken, node.GreaterThanToken.Kind);
+
+ AttachAndCheckDiagnostics(node);
+ }
+
+ [Fact]
+ public void TestModifiedTypeFactoryAndProperties()
+ {
+ var node = GenerateModifiedType();
+
+ Assert.Equal(default, node.Modifiers);
+ Assert.NotNull(node.Type);
+
+ AttachAndCheckDiagnostics(node);
+ }
+
[Fact]
public void TestNullableTypeFactoryAndProperties()
{
@@ -3631,6 +3663,58 @@ public void TestPointerTypeIdentityRewriter()
Assert.Same(oldNode, newNode);
}
+ [Fact]
+ public void TestFunctionPointerTypeTokenDeleteRewriter()
+ {
+ var oldNode = GenerateFunctionPointerType();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestFunctionPointerTypeIdentityRewriter()
+ {
+ var oldNode = GenerateFunctionPointerType();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
+ [Fact]
+ public void TestModifiedTypeTokenDeleteRewriter()
+ {
+ var oldNode = GenerateModifiedType();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestModifiedTypeIdentityRewriter()
+ {
+ var oldNode = GenerateModifiedType();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
[Fact]
public void TestNullableTypeTokenDeleteRewriter()
{
@@ -9019,6 +9103,12 @@ private static ArrayRankSpecifierSyntax GenerateArrayRankSpecifier()
private static PointerTypeSyntax GeneratePointerType()
=> SyntaxFactory.PointerType(GenerateIdentifierName(), SyntaxFactory.Token(SyntaxKind.AsteriskToken));
+ private static FunctionPointerTypeSyntax GenerateFunctionPointerType()
+ => SyntaxFactory.FunctionPointerType(SyntaxFactory.Token(SyntaxKind.DelegateKeyword), SyntaxFactory.Token(SyntaxKind.AsteriskToken), default(SyntaxToken), SyntaxFactory.Token(SyntaxKind.LessThanToken), new SeparatedSyntaxList(), SyntaxFactory.Token(SyntaxKind.GreaterThanToken));
+
+ private static ModifiedType GenerateModifiedType()
+ => SyntaxFactory.ModifiedType(new SyntaxTokenList(), GenerateIdentifierName());
+
private static NullableTypeSyntax GenerateNullableType()
=> SyntaxFactory.NullableType(GenerateIdentifierName(), SyntaxFactory.Token(SyntaxKind.QuestionToken));
@@ -9740,6 +9830,32 @@ public void TestPointerTypeFactoryAndProperties()
Assert.Equal(node, newNode);
}
+ [Fact]
+ public void TestFunctionPointerTypeFactoryAndProperties()
+ {
+ var node = GenerateFunctionPointerType();
+
+ Assert.Equal(SyntaxKind.DelegateKeyword, node.DelegateKeyword.Kind());
+ Assert.Equal(SyntaxKind.AsteriskToken, node.AsteriskToken.Kind());
+ Assert.Equal(SyntaxKind.None, node.CallingConvention.Kind());
+ Assert.Equal(SyntaxKind.LessThanToken, node.LessThanToken.Kind());
+ Assert.Equal(default, node.Arguments);
+ Assert.Equal(SyntaxKind.GreaterThanToken, node.GreaterThanToken.Kind());
+ var newNode = node.WithDelegateKeyword(node.DelegateKeyword).WithAsteriskToken(node.AsteriskToken).WithCallingConvention(node.CallingConvention).WithLessThanToken(node.LessThanToken).WithArguments(node.Arguments).WithGreaterThanToken(node.GreaterThanToken);
+ Assert.Equal(node, newNode);
+ }
+
+ [Fact]
+ public void TestModifiedTypeFactoryAndProperties()
+ {
+ var node = GenerateModifiedType();
+
+ Assert.Equal(default, node.Modifiers);
+ Assert.NotNull(node.Type);
+ var newNode = node.WithModifiers(node.Modifiers).WithType(node.Type);
+ Assert.Equal(node, newNode);
+ }
+
[Fact]
public void TestNullableTypeFactoryAndProperties()
{
@@ -12613,6 +12729,58 @@ public void TestPointerTypeIdentityRewriter()
Assert.Same(oldNode, newNode);
}
+ [Fact]
+ public void TestFunctionPointerTypeTokenDeleteRewriter()
+ {
+ var oldNode = GenerateFunctionPointerType();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestFunctionPointerTypeIdentityRewriter()
+ {
+ var oldNode = GenerateFunctionPointerType();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
+ [Fact]
+ public void TestModifiedTypeTokenDeleteRewriter()
+ {
+ var oldNode = GenerateModifiedType();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestModifiedTypeIdentityRewriter()
+ {
+ var oldNode = GenerateModifiedType();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
[Fact]
public void TestNullableTypeTokenDeleteRewriter()
{
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/FunctionPointerTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/FunctionPointerTests.cs
new file mode 100644
index 0000000000000..e873f68589052
--- /dev/null
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/FunctionPointerTests.cs
@@ -0,0 +1,2951 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Parsing
+{
+ public class FunctionPointerTests : ParsingTests
+ {
+ public FunctionPointerTests(ITestOutputHelper output) : base(output)
+ {
+ }
+
+ [Fact]
+ public void SimpleFunctionPointerTest()
+ {
+ UsingStatement("delegate* ptr;", options: TestOptions.RegularPreview);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Goo");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Theory]
+ [InlineData("cdecl")]
+ [InlineData("managed")]
+ [InlineData("stdcall")]
+ [InlineData("thiscall")]
+ [InlineData("unmanaged")]
+ [InlineData("invalidcallingconvetion")] // This is a semantic error, not a syntax error
+ [InlineData("void")] // This is a semantic error, not a syntax error
+ public void CallingConventions(string conventionString)
+ {
+ UsingStatement($"delegate* {conventionString} ptr;", options: TestOptions.RegularPreview);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(conventionString == "void" ? SyntaxKind.VoidKeyword : SyntaxKind.IdentifierToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Goo");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+ [Fact]
+ public void LangVersion8()
+ {
+ UsingStatement("delegate* cdecl ptr;", options: TestOptions.Regular8,
+ // (1,1): error CS8652: The feature 'function pointers' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
+ // delegate* cdecl ptr;
+ Diagnostic(ErrorCode.ERR_FeatureInPreview, "delegate* cdecl").WithArguments("function pointers").WithLocation(1, 1));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Goo");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void VoidsAsType()
+ {
+ // Void isn't allowed in anything but the return type, but that's a semantic error, not a syntax error
+ UsingStatement("delegate* ptr;", options: TestOptions.RegularPreview);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void NestedFunctionPointers()
+ {
+ UsingStatement("delegate*, delegate* managed> ptr;", options: TestOptions.RegularPreview);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PointerType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ N(SyntaxKind.AsteriskToken);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PointerType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ N(SyntaxKind.AsteriskToken);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PointerType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ N(SyntaxKind.AsteriskToken);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void PointerToAFunctionPointer()
+ {
+ UsingStatement("delegate** ptr;", options: TestOptions.RegularPreview);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.PointerType);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Goo");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.AsteriskToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void RefModifiers()
+ {
+ UsingStatement("delegate*[ ptr;", options: TestOptions.RegularPreview);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.RefKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Goo");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.InKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Bar");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.OutKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Baz");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.RefKeyword);
+ N(SyntaxKind.ReadOnlyKeyword);
+ N(SyntaxKind.PointerType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ N(SyntaxKind.AsteriskToken);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Unterminated_01()
+ {
+ UsingStatement("delegate*< ;", options: TestOptions.RegularPreview,
+ // (1,12): error CS1031: Type expected
+ // delegate*< ;
+ Diagnostic(ErrorCode.ERR_TypeExpected, ";").WithLocation(1, 12),
+ // (1,12): error CS1003: Syntax error, '>' expected
+ // delegate*< ;
+ Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(">", ";").WithLocation(1, 12),
+ // (1,12): error CS1001: Identifier expected
+ // delegate*< ;
+ Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 12));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ M(SyntaxKind.VariableDeclarator);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Unterminated_02()
+ {
+ UsingStatement("delegate*][' expected
+ // delegate*][", ";").WithLocation(1, 15),
+ // (1,15): error CS1001: Identifier expected
+ // delegate*][' expected
+ // delegate*][", ";").WithLocation(1, 19),
+ // (1,19): error CS1001: Identifier expected
+ // delegate*][' expected
+ // delegate*][", ";").WithLocation(1, 20),
+ // (1,20): error CS1001: Identifier expected
+ // delegate*][ ptr;", options: TestOptions.RegularPreview,
+ // (1,11): error CS1003: Syntax error, '<' expected
+ // delegate* Dotted.Name ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, "Dotted").WithArguments("<", "").WithLocation(1, 11),
+ // (1,17): error CS1003: Syntax error, ',' expected
+ // delegate* Dotted.Name ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, ".").WithArguments(",", ".").WithLocation(1, 17));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ M(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "Dotted");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Unterminated_10()
+ {
+ UsingStatement("delegate*( ;", options: TestOptions.RegularPreview,
+ // (1,10): error CS1003: Syntax error, '<' expected
+ // delegate*( ;
+ Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("<", "(").WithLocation(1, 10),
+ // (1,12): error CS1031: Type expected
+ // delegate*( ;
+ Diagnostic(ErrorCode.ERR_TypeExpected, ";").WithLocation(1, 12),
+ // (1,12): error CS1003: Syntax error, '>' expected
+ // delegate*( ;
+ Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(">", ";").WithLocation(1, 12),
+ // (1,12): error CS1001: Identifier expected
+ // delegate*( ;
+ Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 12));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ M(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ M(SyntaxKind.VariableDeclarator);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Unterminated_11()
+ {
+ UsingStatement("delegate* @cdecl>", options: TestOptions.RegularPreview,
+ // (1,11): error CS1003: Syntax error, '<' expected
+ // delegate* @cdecl>
+ Diagnostic(ErrorCode.ERR_SyntaxError, "@cdecl").WithArguments("<", "").WithLocation(1, 11),
+ // (1,17): error CS1003: Syntax error, ',' expected
+ // delegate* @cdecl>
+ Diagnostic(ErrorCode.ERR_SyntaxError, ">").WithArguments(",", ">").WithLocation(1, 17),
+ // (1,18): error CS1002: ; expected
+ // delegate* @cdecl>
+ Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 18));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ M(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "@cdecl");
+ }
+ }
+ M(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void NoParamOrReturnTypes()
+ {
+ UsingStatement("delegate*<> ptr;", options: TestOptions.RegularPreview,
+ // (1,11): error CS1031: Type expected
+ // delegate*<> ptr;
+ Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(1, 11));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UsingParensInsteadOfAngles()
+ {
+ UsingStatement("delegate*(int, void)", options: TestOptions.RegularPreview,
+ // (1,10): error CS1003: Syntax error, '<' expected
+ // delegate*(int, void)
+ Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("<", "(").WithLocation(1, 10),
+ // (1,20): error CS1003: Syntax error, '>' expected
+ // delegate*(int, void)
+ Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(">", ")").WithLocation(1, 20),
+ // (1,21): error CS1001: Identifier expected
+ // delegate*(int, void)
+ Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 21),
+ // (1,21): error CS1002: ; expected
+ // delegate*(int, void)
+ Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 21));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ M(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ M(SyntaxKind.VariableDeclarator);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void MethodTypes()
+ {
+ UsingTree(@"
+class C
+{
+ public delegate* M(delegate* param1, delegate* cdecl param2) {}
+}",
+ options: TestOptions.RegularPreview);
+ N(SyntaxKind.CompilationUnit);
+ {
+ N(SyntaxKind.ClassDeclaration);
+ {
+ N(SyntaxKind.ClassKeyword);
+ N(SyntaxKind.IdentifierToken, "C");
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.MethodDeclaration);
+ {
+ N(SyntaxKind.PublicKeyword);
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.IdentifierToken, "M");
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Parameter);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "C");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.IdentifierToken, "param1");
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.Parameter);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "D");
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.IdentifierToken, "param2");
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ N(SyntaxKind.EndOfFileToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void HardCast()
+ {
+ UsingExpression("(delegate* thiscall)ptr", options: TestOptions.RegularPreview);
+ N(SyntaxKind.CastExpression);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "C");
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void AsCast()
+ {
+ UsingExpression("ptr as delegate* stdcall", options: TestOptions.RegularPreview);
+ N(SyntaxKind.AsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ N(SyntaxKind.AsKeyword);
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void TupleType()
+ {
+ UsingExpression("((delegate* i1, delegate* managed i2))ptr", options: TestOptions.RegularPreview);
+ N(SyntaxKind.CastExpression);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.TupleType);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.TupleElement);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.IdentifierToken, "i1");
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.TupleElement);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "C");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "D");
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.IdentifierToken, "i2");
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void GenericArguments()
+ {
+ UsingExpression("new M, delegate*>()", options: TestOptions.RegularPreview);
+ N(SyntaxKind.ObjectCreationExpression);
+ {
+ N(SyntaxKind.NewKeyword);
+ N(SyntaxKind.GenericName);
+ {
+ N(SyntaxKind.IdentifierToken, "M");
+ N(SyntaxKind.TypeArgumentList);
+ {
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "C");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "D");
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ }
+ N(SyntaxKind.ArgumentList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void TypeOf()
+ {
+ UsingExpression("typeof(delegate* cdecl][)", options: TestOptions.RegularPreview);
+ N(SyntaxKind.TypeOfExpression);
+ {
+ N(SyntaxKind.TypeOfKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.RefKeyword);
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.ReadOnlyKeyword);
+ N(SyntaxKind.RefKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "D");
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void ArrayType()
+ {
+ UsingStatement("delegate*][[] ptr;", options: TestOptions.RegularPreview);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.ArrayType);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.RefKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "C");
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.ArrayRankSpecifier);
+ {
+ N(SyntaxKind.OpenBracketToken);
+ N(SyntaxKind.OmittedArraySizeExpression);
+ {
+ N(SyntaxKind.OmittedArraySizeExpressionToken);
+ }
+ N(SyntaxKind.CloseBracketToken);
+ }
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void DelegateTypes()
+ {
+ UsingNode(@"
+class C
+{
+ delegate delegate* cdecl M(delegate*][ p);
+}",
+ options: TestOptions.RegularPreview);
+ N(SyntaxKind.CompilationUnit);
+ {
+ N(SyntaxKind.ClassDeclaration);
+ {
+ N(SyntaxKind.ClassKeyword);
+ N(SyntaxKind.IdentifierToken, "C");
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.DelegateDeclaration);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.IdentifierToken, "M");
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Parameter);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.RefKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "C");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "D");
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.IdentifierToken, "p");
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ N(SyntaxKind.EndOfFileToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void LambdaParameterType()
+ {
+ UsingExpression("(delegate* p1) => {}", options: TestOptions.RegularPreview);
+ N(SyntaxKind.ParenthesizedLambdaExpression);
+ {
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Parameter);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.IdentifierToken, "p1");
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void LocalVariableAndFunction()
+ {
+ UsingNode(@"
+public void M()
+{
+ delegate* l1;
+ delegate* L2() { }
+ delegate* l3;
+}", options: TestOptions.RegularPreview);
+
+ N(SyntaxKind.CompilationUnit);
+ {
+ N(SyntaxKind.MethodDeclaration);
+ {
+ N(SyntaxKind.PublicKeyword);
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ N(SyntaxKind.IdentifierToken, "M");
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "l1");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ N(SyntaxKind.LocalFunctionStatement);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.IdentifierToken, "L2");
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "l3");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ N(SyntaxKind.EndOfFileToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void IsExpression()
+ {
+ UsingExpression("o is delegate*", options: TestOptions.RegularPreview);
+ N(SyntaxKind.IsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "o");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void IsNamedExpression()
+ {
+ UsingExpression("o is delegate* ptr", options: TestOptions.RegularPreview);
+ N(SyntaxKind.IsPatternExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "o");
+ }
+ N(SyntaxKind.IsKeyword);
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void SwitchStatementCase()
+ {
+ UsingStatement(@"
+switch (o)
+{
+ case delegate* { } _:
+ case delegate* (var x, var y):
+ break;
+}", options: TestOptions.RegularPreview);
+
+ N(SyntaxKind.SwitchStatement);
+ {
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "o");
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchSection);
+ {
+ N(SyntaxKind.CasePatternSwitchLabel);
+ {
+ N(SyntaxKind.CaseKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.PropertyPatternClause);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ N(SyntaxKind.DiscardDesignation);
+ {
+ N(SyntaxKind.UnderscoreToken);
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.CasePatternSwitchLabel);
+ {
+ N(SyntaxKind.CaseKeyword);
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.PositionalPatternClause);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.VarPattern);
+ {
+ N(SyntaxKind.VarKeyword);
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "x");
+ }
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.VarPattern);
+ {
+ N(SyntaxKind.VarKeyword);
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "y");
+ }
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.BreakStatement);
+ {
+ N(SyntaxKind.BreakKeyword);
+ N(SyntaxKind.SemicolonToken);
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void SwitchExpressions()
+ {
+ UsingExpression(@"
+o switch
+{
+ delegate* _ => 1,
+ delegate* (var a, 2) ptr => 2,
+}", options: TestOptions.RegularPreview);
+
+ N(SyntaxKind.SwitchExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "o");
+ }
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.DeclarationPattern);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.DiscardDesignation);
+ {
+ N(SyntaxKind.UnderscoreToken);
+ }
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.SwitchExpressionArm);
+ {
+ N(SyntaxKind.RecursivePattern);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.PositionalPatternClause);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.VarPattern);
+ {
+ N(SyntaxKind.VarKeyword);
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "a");
+ }
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.Subpattern);
+ {
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "2");
+ }
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.SingleVariableDesignation);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.EqualsGreaterThanToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "2");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UsingStatementType()
+ {
+ UsingStatement("using (delegate* ptr = MyMethod()) {}", options: TestOptions.RegularPreview);
+ N(SyntaxKind.UsingStatement);
+ {
+ N(SyntaxKind.UsingKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ N(SyntaxKind.EqualsValueClause);
+ {
+ N(SyntaxKind.EqualsToken);
+ N(SyntaxKind.InvocationExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "MyMethod");
+ }
+ N(SyntaxKind.ArgumentList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ }
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void UsingDeclarationType()
+ {
+ UsingStatement("using delegate* ptr = MyMethod();", options: TestOptions.RegularPreview);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.UsingKeyword);
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ N(SyntaxKind.EqualsValueClause);
+ {
+ N(SyntaxKind.EqualsToken);
+ N(SyntaxKind.InvocationExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "MyMethod");
+ }
+ N(SyntaxKind.ArgumentList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ }
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void FixedStatement()
+ {
+ UsingStatement("fixed (delegate* ptr = &MyMethod) {}", options: TestOptions.RegularPreview);
+ N(SyntaxKind.FixedStatement);
+ {
+ N(SyntaxKind.FixedKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ N(SyntaxKind.EqualsValueClause);
+ {
+ N(SyntaxKind.EqualsToken);
+ N(SyntaxKind.AddressOfExpression);
+ {
+ N(SyntaxKind.AmpersandToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "MyMethod");
+ }
+ }
+ }
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void ForEachVariable()
+ {
+ UsingStatement("foreach (delegate* ptr in ptrs) {}", options: TestOptions.RegularPreview);
+ N(SyntaxKind.ForEachStatement);
+ {
+ N(SyntaxKind.ForEachKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.IdentifierToken, "ptr");
+ N(SyntaxKind.InKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "ptrs");
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void ForVariable()
+ {
+ UsingStatement("for (delegate* ptr = null;;) {}", options: TestOptions.RegularPreview);
+ N(SyntaxKind.ForStatement);
+ {
+ N(SyntaxKind.ForKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ N(SyntaxKind.EqualsValueClause);
+ {
+ N(SyntaxKind.EqualsToken);
+ N(SyntaxKind.NullLiteralExpression);
+ {
+ N(SyntaxKind.NullKeyword);
+ }
+ }
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ N(SyntaxKind.SemicolonToken);
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void SizeOf()
+ {
+ UsingExpression("sizeof(delegate*)", options: TestOptions.RegularPreview);
+ N(SyntaxKind.SizeOfExpression);
+ {
+ N(SyntaxKind.SizeOfKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void SpecifiedParameterNamesAndDefaults()
+ {
+ UsingStatement("delegate* ptr;", options: TestOptions.RegularPreview,
+ // (1,15): error CS1003: Syntax error, ',' expected
+ // delegate* ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, "param1").WithArguments(",", "").WithLocation(1, 15),
+ // (1,30): error CS1003: Syntax error, ',' expected
+ // delegate* ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, "param2").WithArguments(",", "").WithLocation(1, 30));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.StringKeyword);
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void MissingListStart_01()
+ {
+ UsingStatement("delegate*void> ptr;", options: TestOptions.RegularPreview,
+ // (1,10): error CS1003: Syntax error, '<' expected
+ // delegate*void> ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, "void").WithArguments("<", "").WithLocation(1, 10),
+ // (1,10): error CS1001: Identifier expected
+ // delegate*void> ptr;
+ Diagnostic(ErrorCode.ERR_IdentifierExpected, "void").WithLocation(1, 10),
+ // (1,10): error CS1003: Syntax error, ',' expected
+ // delegate*void> ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, "void").WithArguments(",", "void").WithLocation(1, 10));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ M(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ M(SyntaxKind.VariableDeclarator);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void MissingListStart_02()
+ {
+ UsingStatement("delegate* cdecl void> ptr;", options: TestOptions.RegularPreview,
+ // (1,17): error CS1003: Syntax error, '<' expected
+ // delegate* cdecl void> ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, "void").WithArguments("<", "").WithLocation(1, 17),
+ // (1,17): error CS1001: Identifier expected
+ // delegate* cdecl void> ptr;
+ Diagnostic(ErrorCode.ERR_IdentifierExpected, "void").WithLocation(1, 17),
+ // (1,17): error CS1003: Syntax error, ',' expected
+ // delegate* cdecl void> ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, "void").WithArguments(",", "void").WithLocation(1, 17));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken, "cdecl");
+ M(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ M(SyntaxKind.VariableDeclarator);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void MissingListStart_03()
+ {
+ UsingStatement("delegate*> ptr;", options: TestOptions.RegularPreview,
+ // (1,10): error CS1003: Syntax error, '<' expected
+ // delegate*> ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, ">").WithArguments("<", "").WithLocation(1, 10));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ M(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void ManyInvalidModifiers()
+ {
+ UsingStatement("delegate* ptr;", options: TestOptions.RegularPreview);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.ThisKeyword);
+ N(SyntaxKind.ParamsKeyword);
+ N(SyntaxKind.ReadOnlyKeyword);
+ N(SyntaxKind.RefKeyword);
+ N(SyntaxKind.RefKeyword);
+ N(SyntaxKind.ThisKeyword);
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void AsyncInParameterList_InAsyncFunction()
+ {
+ UsingNode(@"
+async void M()
+{
+ delegate* ptr;
+}", options: TestOptions.RegularPreview);
+ N(SyntaxKind.CompilationUnit);
+ {
+ N(SyntaxKind.MethodDeclaration);
+ {
+ N(SyntaxKind.AsyncKeyword);
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ N(SyntaxKind.IdentifierToken, "M");
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "async");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "async");
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ N(SyntaxKind.EndOfFileToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void AsyncInParameterList_InNonAsyncFunction()
+ {
+ UsingNode(@"
+void M()
+{
+ delegate* ptr;
+}", options: TestOptions.RegularPreview);
+ N(SyntaxKind.CompilationUnit);
+ {
+ N(SyntaxKind.MethodDeclaration);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ N(SyntaxKind.IdentifierToken, "M");
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "async");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "async");
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ N(SyntaxKind.EndOfFileToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void AwaitInParameterList_InAsyncFunction()
+ {
+ UsingNode(@"
+async void M()
+{
+ delegate* ptr;
+}", options: TestOptions.RegularPreview,
+ // (4,15): error CS4003: 'await' cannot be used as an identifier within an async method or lambda expression
+ // delegate* ptr;
+ Diagnostic(ErrorCode.ERR_BadAwaitAsIdentifier, "await").WithLocation(4, 15),
+ // (4,22): error CS4003: 'await' cannot be used as an identifier within an async method or lambda expression
+ // delegate* ptr;
+ Diagnostic(ErrorCode.ERR_BadAwaitAsIdentifier, "await").WithLocation(4, 22));
+ N(SyntaxKind.CompilationUnit);
+ {
+ N(SyntaxKind.MethodDeclaration);
+ {
+ N(SyntaxKind.AsyncKeyword);
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ N(SyntaxKind.IdentifierToken, "M");
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "await");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "await");
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ N(SyntaxKind.EndOfFileToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void AwaitInParameterList_InNonAsyncFunction()
+ {
+ UsingNode(@"
+void M()
+{
+ delegate* ptr;
+}", options: TestOptions.RegularPreview);
+ N(SyntaxKind.CompilationUnit);
+ {
+ N(SyntaxKind.MethodDeclaration);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ N(SyntaxKind.IdentifierToken, "M");
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "await");
+ }
+ }
+ N(SyntaxKind.CommaToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "await");
+ }
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ N(SyntaxKind.EndOfFileToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void IncompleteAtEndOfFile()
+ {
+ UsingStatement("delegate*", options: TestOptions.RegularPreview,
+ // (1,10): error CS1003: Syntax error, '<' expected
+ // delegate*
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("<", "").WithLocation(1, 10),
+ // (1,10): error CS1001: Identifier expected
+ // delegate*
+ Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 10),
+ // (1,10): error CS1002: ; expected
+ // delegate*
+ Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 10));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ M(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ M(SyntaxKind.VariableDeclarator);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void IncompleteAtEndOfFileWithIdentifier()
+ {
+ UsingStatement("delegate* cdecl", options: TestOptions.RegularPreview,
+ // (1,11): error CS1003: Syntax error, '<' expected
+ // delegate* cdecl
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("<", "").WithLocation(1, 16),
+ // (1,16): error CS1001: Identifier expected
+ // delegate* cdecl
+ Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 16),
+ // (1,16): error CS1002: ; expected
+ // delegate* cdecl
+ Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 16));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken, "cdecl");
+ M(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ M(SyntaxKind.VariableDeclarator);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void MixedParensAndAngles_01()
+ {
+ UsingStatement("delegate* cdecl' expected
+ // delegate* cdecl", ";").WithLocation(1, 26),
+ // (1,26): error CS1001: Identifier expected
+ // delegate* cdecl ptr;", options: TestOptions.RegularPreview,
+ // (1,16): error CS1003: Syntax error, '<' expected
+ // delegate* cdecl(void> ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, "(").WithArguments("<", "(").WithLocation(1, 16),
+ // (1,21): error CS1003: Syntax error, ',' expected
+ // delegate* cdecl(void> ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, ">").WithArguments(",", ">").WithLocation(1, 21),
+ // (1,26): error CS1003: Syntax error, '>' expected
+ // delegate* cdecl(void> ptr;
+ Diagnostic(ErrorCode.ERR_SyntaxError, ";").WithArguments(">", ";").WithLocation(1, 26),
+ // (1,26): error CS1001: Identifier expected
+ // delegate* cdecl(void> ptr;
+ Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 26));
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken, "cdecl");
+ M(SyntaxKind.LessThanToken);
+ N(SyntaxKind.ModifiedType);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ M(SyntaxKind.VariableDeclarator);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
+ [InlineData("cdecl")]
+ [InlineData("unmanaged")]
+ [InlineData("managed")]
+ [InlineData("stdcall")]
+ [InlineData("thiscall")]
+ [Theory]
+ public void ValidCallingConventionNextLine(string convention)
+ {
+ UsingNode($@"
+void C()
+{{
+ delegate*
+ {convention}
+}}", options: TestOptions.RegularPreview,
+ // (5,10): error CS1003: Syntax error, '<' expected
+ // {convention}
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("<", "").WithLocation(5, convention.Length + 5),
+ // (5,10): error CS1001: Identifier expected
+ // {convention}
+ Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(5, convention.Length + 5),
+ // (5,10): error CS1002: ; expected
+ // {convention}
+ Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(5, convention.Length + 5));
+ N(SyntaxKind.CompilationUnit);
+ {
+ N(SyntaxKind.MethodDeclaration);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ N(SyntaxKind.IdentifierToken, "C");
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ N(SyntaxKind.IdentifierToken, convention);
+ M(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ M(SyntaxKind.VariableDeclarator);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.SemicolonToken);
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ N(SyntaxKind.EndOfFileToken);
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void InvalidCallingConventionNextLine()
+ {
+ UsingNode(@"
+void C()
+{
+ delegate*
+ int ptr = 1;
+}", options: TestOptions.RegularPreview,
+ // (4,14): error CS1003: Syntax error, '<' expected
+ // delegate*
+ Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments("<", "").WithLocation(4, 14),
+ // (4,14): error CS1001: Identifier expected
+ // delegate*
+ Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(4, 14),
+ // (4,14): error CS1002: ; expected
+ // delegate*
+ Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(4, 14));
+ N(SyntaxKind.CompilationUnit);
+ {
+ N(SyntaxKind.MethodDeclaration);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.VoidKeyword);
+ }
+ N(SyntaxKind.IdentifierToken, "C");
+ N(SyntaxKind.ParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.Block);
+ {
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.FunctionPointerType);
+ {
+ N(SyntaxKind.DelegateKeyword);
+ N(SyntaxKind.AsteriskToken);
+ M(SyntaxKind.LessThanToken);
+ M(SyntaxKind.ModifiedType);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.GreaterThanToken);
+ }
+ M(SyntaxKind.VariableDeclarator);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ M(SyntaxKind.SemicolonToken);
+ }
+ N(SyntaxKind.LocalDeclarationStatement);
+ {
+ N(SyntaxKind.VariableDeclaration);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ N(SyntaxKind.VariableDeclarator);
+ {
+ N(SyntaxKind.IdentifierToken, "ptr");
+ N(SyntaxKind.EqualsValueClause);
+ {
+ N(SyntaxKind.EqualsToken);
+ N(SyntaxKind.NumericLiteralExpression);
+ {
+ N(SyntaxKind.NumericLiteralToken, "1");
+ }
+ }
+ }
+ }
+ N(SyntaxKind.SemicolonToken);
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ }
+ N(SyntaxKind.EndOfFileToken);
+ }
+ EOF();
+ }
+ }
+}
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs
index fdcfd02fedbb7..dae0eaf144317 100644
--- a/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/DiagnosticAnalyzerDriver/DiagnosticAnalyzerDriverTests.cs
@@ -30,7 +30,12 @@ public async Task DiagnosticAnalyzerDriverAllInOne()
symbolKindsWithNoCodeBlocks.Add(SymbolKind.Property);
symbolKindsWithNoCodeBlocks.Add(SymbolKind.NamedType);
- var missingSyntaxNodes = new HashSet();
+ var missingSyntaxNodes = new HashSet()
+ {
+ // PROTOYPE(func-ptr): Remove
+ SyntaxKind.FunctionPointerType,
+ SyntaxKind.ModifiedType,
+ };
var analyzer = new CSharpTrackingDiagnosticAnalyzer();
using var workspace = TestWorkspace.CreateCSharp(source, TestOptions.Regular);
]